Leer DLL desde Forms...
Hola amigo mío.
Otra vez con una preguntica...estoy buscando en la ayuda del Developer la forma de leer DLL's, tengo q leer desde un formulario las rutinas de un archivo DLL, pasarle parámetros y recoger lo q la rutina me devuelva.
Como puedo hacer eso?
Saludos desde Venezuela,
Mario.
Otra vez con una preguntica...estoy buscando en la ayuda del Developer la forma de leer DLL's, tengo q leer desde un formulario las rutinas de un archivo DLL, pasarle parámetros y recoger lo q la rutina me devuelva.
Como puedo hacer eso?
Saludos desde Venezuela,
Mario.
1 respuesta
Respuesta de consite
1
1
consite, Diego Rodrigo Munoz Herrera, de 34 anios de edad, estudios en...
Dusculpa la demora, estuvimos en el cierre de año fiscal con Oracle y no te imaginas lo que es ...
Mira: en la nota 73238.1 en matelink encuentras interesantes tips.
Te transcribo la nota:
PURPOSE
This note provides a walkthrough for creating a DLL with Visual C++ 6,
and to attach the DLL to a form. Oracle Developer 2.1 is used.
SCOPE & APPLICATION
Intended for someone who is little or not at all familiar with Visual
C++, and/or someone who has not used FFI and wishes to go through a
step-by-step process of attaching a DLL to a form. This document
does not cover FFI error handling.
Related documents
Note:33006.1 <ml2_documents.showDocument?p_id=33006.1&p_database_id=NOT> - ORA_FFI Error Handling
*********************************************************************
NB! Remember that the Oracle Foreign Function Interface (ORA_FFI) is
a means of accessing libraries local to the operating system, and as
such implies non-portability to other operating systems and to web
deployment.
*********************************************************************
There are three steps:
1) Create the DLL with Microsoft Visual C++ version 6
2) Create the FFI interface using FFI_GEN
3) Create the form and attach the DLL.
Section 1: Create the DLL
=========================
Start Visual C++ from Visual Studio. In Visual Studio, select File->New.
In the resulting window, select the "Projects" tab (it should be selected
already), and select "Win32 Dynamic Link Library". Fill in "Project name",
e.g. test. On the next window select "a DLL that exports some symbols",
and click on "Finish". The last window is the "New project Info" window.
Check the info and click on OK.
At this stage a DLL skeleton with a sample variable, function and class
has been created. On the top left window, select the fileview tab. You
will be able to see test.cpp under "Source files" and test.h under
"Header files".
Remove the class and the variable, which we'll not use. Code snippets
should look like this:
----[test.h]----
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the TEST_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// TEST_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
#ifdef TEST_EXPORTS
#define TEST_API __declspec(dllexport)
#else
#define TEST_API __declspec(dllimport)
#endif
TEST_API int fnTest(void);
----------------
----[test.cpp]----
// test.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include "test.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// This is an example of an exported function.
TEST_API int fnTest(void)
{
return 42;
}
------------------
At this stage you can build the dll by pressing F7 or using the Build menu.
You might want to use the "Build->Set active configuration" to choose to
build a release rather than a debug version, which is much smaller. Once
the DLL has been built, select it in Explorer and right-click on it.
Typically the DLL will be in
X:\Program Files\Microsoft Visual Studio\MyProjects\test\Release. Select
the "Quick view" option. Under the header "Export table" you will see
something like:
Ordinal Entry Point Name
------- ----------- ----
0000 00001010 ?fnTest@@YAHXZ
These are all the symbols that are exported in the DLL. The function name
for fnTest has been mangled to ?fnTest@@YAHXZ; this is a function of the
C++ Compiler and is used to identify different signatures (number of
parameters and their types) of functions to enable overloading. We need to
change fnTest to a C function (i.e. no name mangling). To do this add the
'extern "C"' clause in the source, so that the function looks like this:
----[test.h]----
....
extern "C"
TEST_API int fnTest(void);
----------------
----[test.cpp]----
....
// This is an example of an exported function.
extern "C"
TEST_API int fnTest(void)
{
return 42;
}
------------------
After remaking test.dll, quick view will show
Ordinal Entry Point Name
------- ----------- ----
0000 00001010 fnTest
For the purpose of testing ORA_FFI against different data types, let's add
the following function:
----[test.h]----
....
extern "C"
TEST_API int testFFI (int p1, int *p2, char *p3, double p4, double *p5);
----------------
----[test.cpp]----
....
extern "C"
TEST_API int testFFI (int p1, int *p2, char *p3, double p4, double *p5)
{
p1 = 1001;
*p2 = 1002;
strcpy (p3, "One Thousand and Three");
p4 = 1004.0;
*p5 = 1005.0;
return 2000;
}
------------------
After remaking test.dll, quick view will show
Ordinal Entry Point Name
------- ----------- ----
0000 00001010 fnTest
0001 00001020 testFFI
At this stage we have the DLL (test.dll), with the functions fnTest and
testFFI. The DLL should be placed in a directory on the path. We will
access function testFFI from Forms.
Section 2: Create the FFI interface using FFI_GEN
=================================================
Run FFI_GEN using Forms 5.0. Select "Use the Define-a-function wizard".
This wizard has seven pages:
Page 1: Read the welcome
Page 2: Specify the DLL name, test.dll
Page 3: Enter the function name, testFFI. This is case-sensitive, and must
be entered exactly as seen in the Quick View.
Page 4: Specify the return type, int.
Page 5: Select "C calling standard".
Page 6: Add the function parameters as follows:
Argument name Datatype Pointer
------------- -------- -------
p1 int
p2 int x
p3 char x
p4 double
p5 double x
Page 7: Done!
Now the PLD/PLL must be generated. On the code generator screen, select
"test". Select Tools->Code generation wizard.
Page 1: Read the welcome
Page 2: Select "test"
Page 3: Select the location and name of the .PLD
Page 4: Go!
The pld file is generated, and FFIGEN will automatically start the Forms
generator and compile the pld to pll. Some older versions of FFI_GEN may
not compile the pld to pll, in which case this must be done manually.
At this stage you should have both test.pld and test.pll in the location you
specified.
Section 3: Create the form and attach the PLL
=============================================
For the purpose of this bulletin we will create a simple test form. I used
Forms 5 from Developer 2.1.
Create a new form with a CONTROL block. On the CONTROL block add
five text items, p1 to p5:
Name Datatype Initial value
---- -------- -------------
P1 INTEGER 1
P2 INTEGER 2
p3 CHAR three
P4 NUMBER 4.0
P5 NUMBER 5.0
Set "Database Item" to "No" for all the text items.
Attach test.pll to the form.
Create a button, and add the following code in a WHEN-BUTTON-PRESSED
trigger:
DECLARE
i_p1 INTEGER := :p1;
i_p2 INTEGER := :p2;
s_p3 VARCHAR2(30) := :p3;
r_p4 REAL := :p4;
r_p5 REAL := :p5;
i_rc INTEGER;
BEGIN
i_rc := test.testFFI (i_p1, i_p2, s_p3, r_p4, r_p5);
:p1 := i_p1;
:p2 := i_p2;
:p3 := s_p3;
:p4 := r_p4;
:p5 := r_p5;
MESSAGE ('Return code from testFFI was ' || TO_CHAR (i_rc));
END;
Run the form and press the button. Note that the values for p2, p3
and p5 change as expected, and that a message with return code 2000
appears. The text items p1 and p4 did not change value, even though
the matching parameters for testFFI in the PLL are IN/OUT. The
reason for this lies in the definition of the matching C function:
TEST_API int testFFI (int p1, int *p2, char *p3, double p4, double *p5)
p1 and p4 are not declared as pointer types. Changes to the values of
p1 and p4 are therefore visible inside the C function, but will not
propagate back to the caller due to the pass-by-value nature of C
functions.
The values of p2, p3 and p5 are propagated back to the caller. Even though
the pointers are passed by value, their values point to memory areas which
are the true or original location of the variables (from the caller).
TestFFI updates the original locations of p2, p3 and p5, and hence the
changes are visible to the caller. The reader is referred to any good C
or C++ text for more detail.
Mira: en la nota 73238.1 en matelink encuentras interesantes tips.
Te transcribo la nota:
PURPOSE
This note provides a walkthrough for creating a DLL with Visual C++ 6,
and to attach the DLL to a form. Oracle Developer 2.1 is used.
SCOPE & APPLICATION
Intended for someone who is little or not at all familiar with Visual
C++, and/or someone who has not used FFI and wishes to go through a
step-by-step process of attaching a DLL to a form. This document
does not cover FFI error handling.
Related documents
Note:33006.1 <ml2_documents.showDocument?p_id=33006.1&p_database_id=NOT> - ORA_FFI Error Handling
*********************************************************************
NB! Remember that the Oracle Foreign Function Interface (ORA_FFI) is
a means of accessing libraries local to the operating system, and as
such implies non-portability to other operating systems and to web
deployment.
*********************************************************************
There are three steps:
1) Create the DLL with Microsoft Visual C++ version 6
2) Create the FFI interface using FFI_GEN
3) Create the form and attach the DLL.
Section 1: Create the DLL
=========================
Start Visual C++ from Visual Studio. In Visual Studio, select File->New.
In the resulting window, select the "Projects" tab (it should be selected
already), and select "Win32 Dynamic Link Library". Fill in "Project name",
e.g. test. On the next window select "a DLL that exports some symbols",
and click on "Finish". The last window is the "New project Info" window.
Check the info and click on OK.
At this stage a DLL skeleton with a sample variable, function and class
has been created. On the top left window, select the fileview tab. You
will be able to see test.cpp under "Source files" and test.h under
"Header files".
Remove the class and the variable, which we'll not use. Code snippets
should look like this:
----[test.h]----
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the TEST_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// TEST_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
#ifdef TEST_EXPORTS
#define TEST_API __declspec(dllexport)
#else
#define TEST_API __declspec(dllimport)
#endif
TEST_API int fnTest(void);
----------------
----[test.cpp]----
// test.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include "test.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// This is an example of an exported function.
TEST_API int fnTest(void)
{
return 42;
}
------------------
At this stage you can build the dll by pressing F7 or using the Build menu.
You might want to use the "Build->Set active configuration" to choose to
build a release rather than a debug version, which is much smaller. Once
the DLL has been built, select it in Explorer and right-click on it.
Typically the DLL will be in
X:\Program Files\Microsoft Visual Studio\MyProjects\test\Release. Select
the "Quick view" option. Under the header "Export table" you will see
something like:
Ordinal Entry Point Name
------- ----------- ----
0000 00001010 ?fnTest@@YAHXZ
These are all the symbols that are exported in the DLL. The function name
for fnTest has been mangled to ?fnTest@@YAHXZ; this is a function of the
C++ Compiler and is used to identify different signatures (number of
parameters and their types) of functions to enable overloading. We need to
change fnTest to a C function (i.e. no name mangling). To do this add the
'extern "C"' clause in the source, so that the function looks like this:
----[test.h]----
....
extern "C"
TEST_API int fnTest(void);
----------------
----[test.cpp]----
....
// This is an example of an exported function.
extern "C"
TEST_API int fnTest(void)
{
return 42;
}
------------------
After remaking test.dll, quick view will show
Ordinal Entry Point Name
------- ----------- ----
0000 00001010 fnTest
For the purpose of testing ORA_FFI against different data types, let's add
the following function:
----[test.h]----
....
extern "C"
TEST_API int testFFI (int p1, int *p2, char *p3, double p4, double *p5);
----------------
----[test.cpp]----
....
extern "C"
TEST_API int testFFI (int p1, int *p2, char *p3, double p4, double *p5)
{
p1 = 1001;
*p2 = 1002;
strcpy (p3, "One Thousand and Three");
p4 = 1004.0;
*p5 = 1005.0;
return 2000;
}
------------------
After remaking test.dll, quick view will show
Ordinal Entry Point Name
------- ----------- ----
0000 00001010 fnTest
0001 00001020 testFFI
At this stage we have the DLL (test.dll), with the functions fnTest and
testFFI. The DLL should be placed in a directory on the path. We will
access function testFFI from Forms.
Section 2: Create the FFI interface using FFI_GEN
=================================================
Run FFI_GEN using Forms 5.0. Select "Use the Define-a-function wizard".
This wizard has seven pages:
Page 1: Read the welcome
Page 2: Specify the DLL name, test.dll
Page 3: Enter the function name, testFFI. This is case-sensitive, and must
be entered exactly as seen in the Quick View.
Page 4: Specify the return type, int.
Page 5: Select "C calling standard".
Page 6: Add the function parameters as follows:
Argument name Datatype Pointer
------------- -------- -------
p1 int
p2 int x
p3 char x
p4 double
p5 double x
Page 7: Done!
Now the PLD/PLL must be generated. On the code generator screen, select
"test". Select Tools->Code generation wizard.
Page 1: Read the welcome
Page 2: Select "test"
Page 3: Select the location and name of the .PLD
Page 4: Go!
The pld file is generated, and FFIGEN will automatically start the Forms
generator and compile the pld to pll. Some older versions of FFI_GEN may
not compile the pld to pll, in which case this must be done manually.
At this stage you should have both test.pld and test.pll in the location you
specified.
Section 3: Create the form and attach the PLL
=============================================
For the purpose of this bulletin we will create a simple test form. I used
Forms 5 from Developer 2.1.
Create a new form with a CONTROL block. On the CONTROL block add
five text items, p1 to p5:
Name Datatype Initial value
---- -------- -------------
P1 INTEGER 1
P2 INTEGER 2
p3 CHAR three
P4 NUMBER 4.0
P5 NUMBER 5.0
Set "Database Item" to "No" for all the text items.
Attach test.pll to the form.
Create a button, and add the following code in a WHEN-BUTTON-PRESSED
trigger:
DECLARE
i_p1 INTEGER := :p1;
i_p2 INTEGER := :p2;
s_p3 VARCHAR2(30) := :p3;
r_p4 REAL := :p4;
r_p5 REAL := :p5;
i_rc INTEGER;
BEGIN
i_rc := test.testFFI (i_p1, i_p2, s_p3, r_p4, r_p5);
:p1 := i_p1;
:p2 := i_p2;
:p3 := s_p3;
:p4 := r_p4;
:p5 := r_p5;
MESSAGE ('Return code from testFFI was ' || TO_CHAR (i_rc));
END;
Run the form and press the button. Note that the values for p2, p3
and p5 change as expected, and that a message with return code 2000
appears. The text items p1 and p4 did not change value, even though
the matching parameters for testFFI in the PLL are IN/OUT. The
reason for this lies in the definition of the matching C function:
TEST_API int testFFI (int p1, int *p2, char *p3, double p4, double *p5)
p1 and p4 are not declared as pointer types. Changes to the values of
p1 and p4 are therefore visible inside the C function, but will not
propagate back to the caller due to the pass-by-value nature of C
functions.
The values of p2, p3 and p5 are propagated back to the caller. Even though
the pointers are passed by value, their values point to memory areas which
are the true or original location of the variables (from the caller).
TestFFI updates the original locations of p2, p3 and p5, and hence the
changes are visible to the caller. The reader is referred to any good C
or C++ text for more detail.
- Compartir respuesta
- Anónimo
ahora mismo