Windows 32-bit DLLs with Harbour Code - Any More Progress
Windows 32-bit DLLs with Harbour Code - Any More Progress
Hello,
FWH8.05/BCC5.5 is now my development environment.
I have read the posts on creating a self contained DLL in Harbour that can be called from other programming platforms.
It seems that the one called level 1 (maindll.c Windows self-contained DLL entry point) would be the easiest to implement ... but may be limited to one parameter being passed.
Has any one successfully implemented a DLL function call from another programming language to a function defined in Harbour within the Windows environment. If so, would you be kind enough to share your approach.
I am new to Harbour (I've got a FiveWin++ background) and so would like a little "kick in the right direction".
My application that I would like to port over is written in FW++/Alaska XBase++/c/c++. I use c/c++ to increase performance when calculating crc's, string manipulations and querying hardware for status.
Any guidance would be appreciated.
Thank you
Angelo C
FWH8.05/BCC5.5 is now my development environment.
I have read the posts on creating a self contained DLL in Harbour that can be called from other programming platforms.
It seems that the one called level 1 (maindll.c Windows self-contained DLL entry point) would be the easiest to implement ... but may be limited to one parameter being passed.
Has any one successfully implemented a DLL function call from another programming language to a function defined in Harbour within the Windows environment. If so, would you be kind enough to share your approach.
I am new to Harbour (I've got a FiveWin++ background) and so would like a little "kick in the right direction".
My application that I would like to port over is written in FW++/Alaska XBase++/c/c++. I use c/c++ to increase performance when calculating crc's, string manipulations and querying hardware for status.
Any guidance would be appreciated.
Thank you
Angelo C
- Roger Seiler
- Posts: 223
- Joined: Thu Dec 01, 2005 3:34 pm
- Location: Nyack, New York, USA
- Contact:
Yes, it can be done using the FWH command DLL32. Go to ..\fwh\manual\fwcmd.chm and go to DLL to see the help topic explaining this.
You can see an example of how to do this in a set of DLL32 calls that I put together in order to use the Protection PLUS 3rd part tool that is implemented with a DLL programmed in C. Just click below to download this example (though it does not include the PLUS dll)...
http://www.leadersoft.com/software/ppp4xhb.zip
Then after you download and unzip the ppp4xhb.zip file, take a look at the ppp4fwh.prg file to see the example for using the DLL32 command.
- Roger
You can see an example of how to do this in a set of DLL32 calls that I put together in order to use the Protection PLUS 3rd part tool that is implemented with a DLL programmed in C. Just click below to download this example (though it does not include the PLUS dll)...
http://www.leadersoft.com/software/ppp4xhb.zip
Then after you download and unzip the ppp4xhb.zip file, take a look at the ppp4fwh.prg file to see the example for using the DLL32 command.
- Roger
- Antonio Linares
- Site Admin
- Posts: 37481
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Angelo,
There are three types of DLLs that you can create. From the Harbour docs:
Windows 32-bit DLLs with Harbour code
=====================================
Programs created with Clipper or Harbour are traditionally a
monolithic EXE containing all executable code. This includes
the Virtual Machine (VM) and the RunTime Library (RTL) as well as
your own code. Running under Windows (Win32) with Harbour, you
can now also create and use Windows DLLs that contain PRG code.
Harbour supports Win32 DLLs in 3 ways.
1) Self-contained DLLs containing functions from any platform.
(These are not what we call a "Harbour.dll", although they may
be named that. The DLL entry points are different.)
These have the VM/RTL inside them and can be used by any other
Windows program. You can create a .lib for static linking,
or use GetProcAddress as in any standard Win32 DLL.
Calling Harbour/Prg functions directly is limited to
those that take no parameters unless you include C functions
in the DLL that take parameters and then call the PRG-level
code.
To do static linking, do this to create the .lib:
implib harbour.lib harbour.dll
For the Borland C platform, use that library and import32.lib
and cw32.lib from Borland, and you are ready to go.
See contrib\delphi\hbdll for an example of a Delphi program that can
use all of Harbour's functionality by accessing a self-contained DLL.
BLD_SDLL.BAT is used there to create the DLL.
2) PCode EXEs using a Harbour.dll
A Harbour.dll is designed to be called from a Harbour app.
A pcode EXE is a small Harbour executable that does not contain the
VM/RTL. To execute its functions, it must load and access a
Harbour.dll.
If you want dynamic linking, then use this to execute a Harbour
dynamically loaded pcode DLL function or procedure:
HB_DllDo( <cFuncName> [,<params...>] ) --> [<uResult>]
This lets you have all your common code in a DLL, and have lots
of small EXEs that use it. Realize however that, even though this
may be a nice way to manage your code, each EXE may
load its own image of the Harbour.dll into memory at runtime.
In terms of Windows memory, there may not be a benefit to using pcode
EXEs over monolithic EXEs. But it may be a worthwhile maintenance
benefit to have lots of replaceable small exes.
3) PCode DLLs used from traditional EXEs
A pcode DLL does not contain the VM/RTL.
It is a library of Harbour-compiled PRG code that uses the VM/RTL
of the EXE that calls it. This has the benefit of having
replaceable modules in DLLs that don't necessarily require updating
your EXE.
The following is clipped from a msg by Antonio Linares to the Harbour
developer list explaining some of the details:
Please notice that there are three different Windows DLL entry points:
+ source/vm/
* maindll.c Windows self-contained DLL entry point
* maindllh.c Windows Harbour DLL entry point (harbour.dll)
* maindllp.c Windows pcode DLL entry point and VM/RTL routing functions
> * maindll.c Windows self-contained DLL entry point
To produce Harbour code, as DLLs, that may be used
from other programming languages applications (as VB,
Delphi, C++, etc...)
> * maindllh.c Windows Harbour DLL entry point (harbour.dll)
To produce Harbour.dll, to be just used from small pcode Harbour EXEs
> * maindllp.c Windows pcode DLL entry point and VM/RTL routing
To produce small pcode DLLs, to be used just from Harbour EXE apps.
maindllp.c is the entry point for the Harbour pcode DLLs. pcode DLLs
are quite small DLLs, that just contain pcode and/or C (using extend
api) functions.
mainwin.c is the entry point for Windows EXEs, not for DLLs.
You may use maindll.c, maindllh.c or maindllp.c based on
your needs.
If you are looking to build a Harbour.dll, then you must use
maindllh.c
There are three types of DLLs that you can create. From the Harbour docs:
Windows 32-bit DLLs with Harbour code
=====================================
Programs created with Clipper or Harbour are traditionally a
monolithic EXE containing all executable code. This includes
the Virtual Machine (VM) and the RunTime Library (RTL) as well as
your own code. Running under Windows (Win32) with Harbour, you
can now also create and use Windows DLLs that contain PRG code.
Harbour supports Win32 DLLs in 3 ways.
1) Self-contained DLLs containing functions from any platform.
(These are not what we call a "Harbour.dll", although they may
be named that. The DLL entry points are different.)
These have the VM/RTL inside them and can be used by any other
Windows program. You can create a .lib for static linking,
or use GetProcAddress as in any standard Win32 DLL.
Calling Harbour/Prg functions directly is limited to
those that take no parameters unless you include C functions
in the DLL that take parameters and then call the PRG-level
code.
To do static linking, do this to create the .lib:
implib harbour.lib harbour.dll
For the Borland C platform, use that library and import32.lib
and cw32.lib from Borland, and you are ready to go.
See contrib\delphi\hbdll for an example of a Delphi program that can
use all of Harbour's functionality by accessing a self-contained DLL.
BLD_SDLL.BAT is used there to create the DLL.
2) PCode EXEs using a Harbour.dll
A Harbour.dll is designed to be called from a Harbour app.
A pcode EXE is a small Harbour executable that does not contain the
VM/RTL. To execute its functions, it must load and access a
Harbour.dll.
If you want dynamic linking, then use this to execute a Harbour
dynamically loaded pcode DLL function or procedure:
HB_DllDo( <cFuncName> [,<params...>] ) --> [<uResult>]
This lets you have all your common code in a DLL, and have lots
of small EXEs that use it. Realize however that, even though this
may be a nice way to manage your code, each EXE may
load its own image of the Harbour.dll into memory at runtime.
In terms of Windows memory, there may not be a benefit to using pcode
EXEs over monolithic EXEs. But it may be a worthwhile maintenance
benefit to have lots of replaceable small exes.
3) PCode DLLs used from traditional EXEs
A pcode DLL does not contain the VM/RTL.
It is a library of Harbour-compiled PRG code that uses the VM/RTL
of the EXE that calls it. This has the benefit of having
replaceable modules in DLLs that don't necessarily require updating
your EXE.
The following is clipped from a msg by Antonio Linares to the Harbour
developer list explaining some of the details:
Please notice that there are three different Windows DLL entry points:
+ source/vm/
* maindll.c Windows self-contained DLL entry point
* maindllh.c Windows Harbour DLL entry point (harbour.dll)
* maindllp.c Windows pcode DLL entry point and VM/RTL routing functions
> * maindll.c Windows self-contained DLL entry point
To produce Harbour code, as DLLs, that may be used
from other programming languages applications (as VB,
Delphi, C++, etc...)
> * maindllh.c Windows Harbour DLL entry point (harbour.dll)
To produce Harbour.dll, to be just used from small pcode Harbour EXEs
> * maindllp.c Windows pcode DLL entry point and VM/RTL routing
To produce small pcode DLLs, to be used just from Harbour EXE apps.
maindllp.c is the entry point for the Harbour pcode DLLs. pcode DLLs
are quite small DLLs, that just contain pcode and/or C (using extend
api) functions.
mainwin.c is the entry point for Windows EXEs, not for DLLs.
You may use maindll.c, maindllh.c or maindllp.c based on
your needs.
If you are looking to build a Harbour.dll, then you must use
maindllh.c
Hello
Thank you for your replies. It's made me think a little more.
As a example. I used the Tutor01.prg in the Sample directory as such:
Build as .DLL by executing Buildhd tutor01
I get the Tutor01.dll file OK.
To get a *.lib file so that I can statically link the DLL with another programme, I perform:
Implib tutor01.lib tutor01.dll
I get the Tutor01.lib file OK.
When I check the Tutor01.lib file, I have not got any DLL Import Symbol references to Main (or AppSys) which are defined in Tutor01.
How can I force Harbour to export these function names from the *.prg source?
Best Regards,
Angelo C
Thank you for your replies. It's made me think a little more.
As a example. I used the Tutor01.prg in the Sample directory as such:
Build as .DLL by executing Buildhd tutor01
I get the Tutor01.dll file OK.
To get a *.lib file so that I can statically link the DLL with another programme, I perform:
Implib tutor01.lib tutor01.dll
I get the Tutor01.lib file OK.
When I check the Tutor01.lib file, I have not got any DLL Import Symbol references to Main (or AppSys) which are defined in Tutor01.
How can I force Harbour to export these function names from the *.prg source?
Best Regards,
Angelo C
- Antonio Linares
- Site Admin
- Posts: 37481
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Angelo,
We had not provided you maindll.obj properly compiled (because HB_EXPORT required -D__EXPORT__ flag).
Here you have the right one:
http://rapidshare.com/files/123510556/maindll.obj.html
Now the DLL has three entry points as declared in maindll.c:
As you see you have three choices: To invoke a procedure by its name without parameters, or to supply one or two parameters to it.
In case that you are not calling the DLL from Harbour (so you don't have Harbour items) you can easily modify those C functions to create the items for you.
If you need some more explanations or examples, just tell me
We had not provided you maindll.obj properly compiled (because HB_EXPORT required -D__EXPORT__ flag).
Here you have the right one:
http://rapidshare.com/files/123510556/maindll.obj.html
Now the DLL has three entry points as declared in maindll.c:
Code: Select all
HB_EXPORT LONG PASCAL HBDLLENTRY( char * cProcName )
{
hb_itemDoC( cProcName, 0, 0 );
return 0;
}
HB_EXPORT LONG PASCAL HBDLLENTRY1( char * cProcName, LONG pItem )
{
hb_itemDoC( cProcName, 1, ( PHB_ITEM ) pItem, 0 );
return 0;
}
HB_EXPORT LONG PASCAL HBDLLENTRY2( char * cProcName, LONG pItem1, LONG pItem2 )
{
hb_itemDoC( cProcName, 2, ( PHB_ITEM ) pItem1, ( PHB_ITEM ) pItem2, 0 );
return 0;
}
In case that you are not calling the DLL from Harbour (so you don't have Harbour items) you can easily modify those C functions to create the items for you.
If you need some more explanations or examples, just tell me
Thanks Antonio,
I compiled and linked with the updated maindll.obj file and it worked OK.
I now am trying to pass one parameter from testdll to tutor01 program. I modified the source of the programmes to the following:
TUTOR01.PRG:
// Typical Welcome message, from Windows!
// FWVERSION, FWCOPYRIGHT and FWDESCRIPTION are just
// some defines placed at FiveWin.ch to support four versions:
// Clipper, Xbase++, Harbour/xHarbour and C3!
#include "FiveWin.ch"
//----------------------------------------------------------------------------//
function Main()
MsgInfo( FWVERSION + Chr( 13 ) + FWCOPYRIGHT, FWDESCRIPTION )
return nil
function OneParam(Param1)
MsgInfo(Param1)
return nil
//----------------------------------------------------------------------------//
procedure AppSys // XBase++ requirement
return
//----------------------------------------------------------------------------//
TESTDLL.PRG:
// Using Harbour DLLs
// To build Tutor01.dll do: buildhd.bat tutor01
#include "FiveWin.ch"
function Main()
local Test_String
HbDLLEntry( "MAIN" )
Test_String := "Hello world from AC!" //String passed
HbDLLEntry1( "ONEPARAM", Test_String) //Passing a String to DLL function "OneParam"
MsgInfo( "ok from EXE" )
return nil
DLL FUNCTION HBDLLENTRY( cProc AS LPSTR ) AS LONG PASCAL LIB "Tutor01.dll"
DLL FUNCTION HBDLLENTRY1( cProc AS LPSTR , pItem AS LONG) AS LONG PASCAL LIB "Tutor01.dll"
I compile and link OK. But when I run it, I get the first message box with FWVERSION, FWCOPYRIGHT and FWDESCRIPTION text OK.
However the second passed parameter results in an
Best Regards, Angelo C
I compiled and linked with the updated maindll.obj file and it worked OK.
I now am trying to pass one parameter from testdll to tutor01 program. I modified the source of the programmes to the following:
TUTOR01.PRG:
// Typical Welcome message, from Windows!
// FWVERSION, FWCOPYRIGHT and FWDESCRIPTION are just
// some defines placed at FiveWin.ch to support four versions:
// Clipper, Xbase++, Harbour/xHarbour and C3!
#include "FiveWin.ch"
//----------------------------------------------------------------------------//
function Main()
MsgInfo( FWVERSION + Chr( 13 ) + FWCOPYRIGHT, FWDESCRIPTION )
return nil
function OneParam(Param1)
MsgInfo(Param1)
return nil
//----------------------------------------------------------------------------//
procedure AppSys // XBase++ requirement
return
//----------------------------------------------------------------------------//
TESTDLL.PRG:
// Using Harbour DLLs
// To build Tutor01.dll do: buildhd.bat tutor01
#include "FiveWin.ch"
function Main()
local Test_String
HbDLLEntry( "MAIN" )
Test_String := "Hello world from AC!" //String passed
HbDLLEntry1( "ONEPARAM", Test_String) //Passing a String to DLL function "OneParam"
MsgInfo( "ok from EXE" )
return nil
DLL FUNCTION HBDLLENTRY( cProc AS LPSTR ) AS LONG PASCAL LIB "Tutor01.dll"
DLL FUNCTION HBDLLENTRY1( cProc AS LPSTR , pItem AS LONG) AS LONG PASCAL LIB "Tutor01.dll"
I compile and link OK. But when I run it, I get the first message box with FWVERSION, FWCOPYRIGHT and FWDESCRIPTION text OK.
However the second passed parameter results in an
with the folowing three lines of text:Harbour Exception window
Can you help me on this one as well?CALLED FROM CALLDLL(0)
CALLED FROM HBDLLENTRY1( 18 )
CALLED FROM MAIN(12)
Best Regards, Angelo C
Hello again.
I am experimenting some more with DLL calls in FWH8.06
Can you advise me on how to compile the maindll.c source to produce the
maindll.obj properly compiled (you mentioned before that it requies the -D__EXPORT__ flag). I have downloaded the compiler/linker tools you suggested.
Also, can you supply me with a C/C++ code example of the pItem Structure so that I can pass parameters from Applications written in C/C++ to FWH using DLLs.
Thanks for your time in considering and actioning this request.
Best Regards,
Angelo.c
I am experimenting some more with DLL calls in FWH8.06
Can you advise me on how to compile the maindll.c source to produce the
maindll.obj properly compiled (you mentioned before that it requies the -D__EXPORT__ flag). I have downloaded the compiler/linker tools you suggested.
Also, can you supply me with a C/C++ code example of the pItem Structure so that I can pass parameters from Applications written in C/C++ to FWH using DLLs.
Thanks for your time in considering and actioning this request.
Best Regards,
Angelo.c
- Antonio Linares
- Site Admin
- Posts: 37481
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
- Antonio Linares
- Site Admin
- Posts: 37481
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Angelo,
Instead of trying to build Harbour items externally, it is much simpler if you let Harbour build them
Here you have a working example:
MYDLL.PRG - build it using fwh\samples\buildhd.bat
TestMyDL.prg - EXE that will use the DLL
Instead of trying to build Harbour items externally, it is much simpler if you let Harbour build them
Here you have a working example:
MYDLL.PRG - build it using fwh\samples\buildhd.bat
Code: Select all
//----------------------------------------------------------------------------//
function Main()
MsgInfo( "Inside DLL main()" )
return nil
//----------------------------------------------------------------------------//
function OneParam( x )
MsgInfo( x )
return nil
//----------------------------------------------------------------------------//
#pragma BEGINDUMP
#include <windows.h>
#include <hbapi.h>
#include <hbapiitm.h>
__declspec( dllexport ) LONG pascal DOPROC( char * cProcName, char * cParam )
{
PHB_ITEM pItem = hb_itemPutC( NULL, cParam ); // Harbour builds the item !!!
if( cProcName )
{
hb_itemDoC( cProcName, 1, ( PHB_ITEM ) pItem, 0 );
hb_itemRelease( pItem );
}
else
MessageBox( 0, "inside the DLL", "DOPROC", 0 );
return 0;
}
#pragma ENDDUMP
//----------------------------------------------------------------------------//
Code: Select all
#include "FiveWin.ch"
function Main()
local cString := "Hello world!"
DOPROC( "ONEPARAM", cString )
MsgInfo( "ok from EXE" )
return nil
DLL FUNCTION DOPROC( cProc AS LPSTR, cText AS LPSTR ) AS LONG PASCAL LIB "MYDLL.dll"
- Antonio Linares
- Site Admin
- Posts: 37481
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
And now, accessing the same DLL from a C code EXE:
testc.c:
To build it do:
c:\bcc55\bin\bcc32 -c testc.c
c:\bcc55\bin\ilink32 -aa -Tpe c:\bcc55\lib\c0w32.obj testc.obj, testc.exe,,c:\bcc55\lib\cw32.lib c:\bcc55\lib\import32.lib
testc.c:
Code: Select all
#include <windows.h>
typedef long pascal ( * DOPROC ) ( char * cProcName, char * cString );
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
HINSTANCE hDLL = LoadLibrary( "MyDLL.DLL" );
DOPROC pDoProc = ( DOPROC ) GetProcAddress( hDLL, "DOPROC" );
pDoProc( "ONEPARAM", "Hello world!" );
MessageBox( 0, "back in C EXE", "ok", 0 );
FreeLibrary( hDLL );
return 0;
}
c:\bcc55\bin\bcc32 -c testc.c
c:\bcc55\bin\ilink32 -aa -Tpe c:\bcc55\lib\c0w32.obj testc.obj, testc.exe,,c:\bcc55\lib\cw32.lib c:\bcc55\lib\import32.lib
Thank you Antonio for that information. I can now call a FWH DLL from FWH compiled code and C/C++ compiled code and pass appropiate parameters (Experimented with strings and integers to date).
I extended your examples to cover simultaneous string and integer parameter passing into the DLL written in FWH. Here is the updated code for people's reference. It compiles and runs OK on my system/environment setup for FWH8.06
MyDLL.prg: (Compile as you advised on the previous post.)
TestMyDLL.prg: (Build as you advised on the previous post.)
And now, accessing the same DLL from a C code EXE:
(Compile and Link as you advised on the previous post.)
Testc.c
That's it. Please notice that for passed strings, I use hb_itemPutC( NULL, cParam_2 ) and for integers I use hb_itemPutNI( NULL, nParam_3 )
I referenced the Harbour C Source module vm\hbapi.h to get an idea of what hb_itemPutxxxx routine to use. Now I think it's just a matter of experimenting with other parameters types such as dates, doubles, long etc to ensure I can use FWH routines from other languages.
Thanks for your help.
Best regards,
Angelo C
I extended your examples to cover simultaneous string and integer parameter passing into the DLL written in FWH. Here is the updated code for people's reference. It compiles and runs OK on my system/environment setup for FWH8.06
MyDLL.prg: (Compile as you advised on the previous post.)
Code: Select all
//5th July 2008. Testing User Defined DLL entry points into FWH
//----------------------------------------------------------------------------//
function Main()
MsgInfo( "Inside DLL main()" )
return nil
//----------------------------------------------------------------------------//
function OneParam( x )
MsgInfo( x )
return nil
function TwoParam( x , y)
MsgInfo( x )
MsgInfo( y )
return nil
function ThreeParam( cx, cy, nz)
MsgInfo( cx )
MsgInfo( cy )
MsgInfo( nz + 6)
MsgInfo( valtype(nz))
return nil
//----------------------------------------------------------------------------//
#pragma BEGINDUMP
#include <windows.h>
#include <hbapi.h>
#include <hbapiitm.h>
__declspec( dllexport ) LONG pascal DOPROC( char * cProcName, char * cParam )
{
PHB_ITEM pItem = hb_itemPutC( NULL, cParam ); // Harbour builds the item !!!
if( cProcName )
{
hb_itemDoC( cProcName, 1, ( PHB_ITEM ) pItem, 0 );
hb_itemRelease( pItem );
}
else
MessageBox( 0, "inside the DLL ... One Parameter", "DOPROC", 0 );
return 0;
}
__declspec( dllexport ) LONG pascal DOPROC_2( char * cProcName, char * cParam, char * cParam_2 )
{
PHB_ITEM pItem = hb_itemPutC( NULL, cParam ); // Harbour builds the item !!! 1st Parameter ... String
PHB_ITEM pItem_2 = hb_itemPutC( NULL, cParam_2 ); // Harbour builds the item !!! 2nd parameter ... String
if( cProcName )
{
hb_itemDoC( cProcName, 2, ( PHB_ITEM ) pItem, ( PHB_ITEM ) pItem_2, 0 );
hb_itemRelease( pItem );
hb_itemRelease( pItem_2);
}
else
MessageBox( 0, "inside the DLL ... Two Parameters", "DOPROC_2", 0 );
return 0;
}
__declspec( dllexport ) LONG pascal DOPROC_3( char * cProcName, char * cParam, char * cParam_2, int nParam_3 )
{
PHB_ITEM pItem = hb_itemPutC( NULL, cParam ); // Harbour builds the item !!! 1st Parameter ... String
PHB_ITEM pItem_2 = hb_itemPutC( NULL, cParam_2 ); // Harbour builds the item !!! 2nd parameter ... String
PHB_ITEM pItem_3 = hb_itemPutNI( NULL, nParam_3 ); // Harbour builds the item !!! 3rd parameter ... Integer
if( cProcName )
{
hb_itemDoC( cProcName, 3, ( PHB_ITEM ) pItem, ( PHB_ITEM ) pItem_2, ( PHB_ITEM ) pItem_3, 0 );
hb_itemRelease( pItem );
hb_itemRelease( pItem_2 );
hb_itemRelease( pItem_3 );
}
else
MessageBox( 0, "inside the DLL ... Three Parameters (2 strings, 1 integer)", "DOPROC_3", 0 );
return 0;
}
#pragma ENDDUMP
//----------------------------------------------------------------------------//
TestMyDLL.prg: (Build as you advised on the previous post.)
Code: Select all
//5th July 2008. Testing User Defined DLL entry points into FWH
// This Module tests the *.Exe generated by FWH that will use the DLL
//----------------------------------------------------------------------------//
#include "FiveWin.ch"
function Main()
local cString := "Hello world from AC!"
local cString_2 := "Hello world from AC ... String 2!"
local nVal_3 := 4 //Integer value
DOPROC( "ONEPARAM", cString )
MsgInfo( "ok from EXE for One Parameter (one String)" )
DOPROC_2( "TWOPARAM", cString, cString_2 )
MsgInfo( "ok from EXE for Two Parameters (Two Strings)" )
DOPROC_3( "THREEPARAM", cString, cString_2, nVal_3 )
MsgInfo( "ok from EXE for Two Parameters (Two Strings) and a Numeric value" )
return nil
DLL FUNCTION DOPROC( cProc AS LPSTR, cText AS LPSTR ) AS LONG PASCAL LIB "MYDLL.dll"
DLL FUNCTION DOPROC_2( cProc AS LPSTR, cText AS LPSTR, cText_2 AS LPSTR ) AS LONG PASCAL LIB "MYDLL.dll"
DLL FUNCTION DOPROC_3( cProc AS LPSTR, cText AS LPSTR, cText_2 AS LPSTR, nVal AS WORD ) AS LONG PASCAL LIB "MYDLL.dll"
//----------------------------------------------------------------------------//
And now, accessing the same DLL from a C code EXE:
(Compile and Link as you advised on the previous post.)
Testc.c
Code: Select all
//5th July 2008. Testing C Code exe to call DLL written in FWH
#include <windows.h>
typedef long pascal ( * DOPROC ) ( char * cProcName, char * cString );
typedef long pascal ( * DOPROC_2 ) ( char * cProcName, char * cString, char * cString_2 );
typedef long pascal ( * DOPROC_3 ) ( char * cProcName, char * cString, char * cString_2, int nx );
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
int nx;
HINSTANCE hDLL = LoadLibrary( "MyDLL.DLL" );
DOPROC pDoProc = ( DOPROC ) GetProcAddress( hDLL, "DOPROC" );
DOPROC_2 pDoProc_2 = ( DOPROC_2 ) GetProcAddress( hDLL, "DOPROC_2" );
DOPROC_3 pDoProc_3 = ( DOPROC_3 ) GetProcAddress( hDLL, "DOPROC_3" );
pDoProc( "ONEPARAM", "Hello world!" );
MessageBox( 0, "back in C EXE from Passing One String Parameter to DLL", "ok", 0 );
pDoProc_2( "TWOPARAM", "Hello world .. No 1!", "Hello world .. No 2!" );
MessageBox( 0, "back in C EXE from Passing Two String Parameter to DLL", "ok", 0 );
nx = 5;
pDoProc_3( "THREEPARAM", "Hello world .. No 1!", "Hello world .. No 2!", nx );
MessageBox( 0, "back in C EXE from Passing Two String Parameter and a Numeric to DLL", "ok", 0 );
FreeLibrary( hDLL );
return 0;
}
//----------------------------------------------------------------------------//
That's it. Please notice that for passed strings, I use hb_itemPutC( NULL, cParam_2 ) and for integers I use hb_itemPutNI( NULL, nParam_3 )
I referenced the Harbour C Source module vm\hbapi.h to get an idea of what hb_itemPutxxxx routine to use. Now I think it's just a matter of experimenting with other parameters types such as dates, doubles, long etc to ensure I can use FWH routines from other languages.
Thanks for your help.
Best regards,
Angelo C
Hello
Is it possible to pass instantiated objects from a FW++ exe application to FWH *.dll code?
What I would like to do is to have my current application (which is mainly written in FW++) call and pass objects to a FWH DLL code. My current application extensively uses C/C++ routines called from my FW++ code to speed up execution.
My aim to to transition to FWH totally but want to do this in small incremental stages so that I can continue to use my FW++ application with minimal disruption and also getting the extra capabilites of FWH.
Best Regards,
Angelo C
Is it possible to pass instantiated objects from a FW++ exe application to FWH *.dll code?
What I would like to do is to have my current application (which is mainly written in FW++) call and pass objects to a FWH DLL code. My current application extensively uses C/C++ routines called from my FW++ code to speed up execution.
My aim to to transition to FWH totally but want to do this in small incremental stages so that I can continue to use my FW++ application with minimal disruption and also getting the extra capabilites of FWH.
Best Regards,
Angelo C
- Antonio Linares
- Site Admin
- Posts: 37481
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Como retornar resultados da funcoes da DLL, como se faz ?
como pegar o retorno da minha DLL e retornar para o EXE ?
Code: Select all
__declspec( dllexport ) LONG pascal DOPROC( char * cProcName, char * cParam )
{
PHB_ITEM pItem = hb_itemPutC( NULL, cParam ); // Harbour builds the item !!!
if( cProcName )
{
---> hb_itemDoC( cProcName, 1, ( PHB_ITEM ) pItem, 0 );
hb_itemRelease( pItem );
}
else
MessageBox( 0, "inside the DLL ... One Parameter", "DOPROC", 0 );
---> return 0; }
- Antonio Linares
- Site Admin
- Posts: 37481
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Ari,
In this example we are returning a LONG value from the DLL, so you can do it this way:
If you need to return other types of values (logical -BOOL-, string -char*-) then you have to change the function to return those values instead of a LONG.
In this example we are returning a LONG value from the DLL, so you can do it this way:
Code: Select all
__declspec( dllexport ) LONG pascal DOPROC( char * cProcName, char * cParam )
{
PHB_ITEM pItem = hb_itemPutC( NULL, cParam ); // Harbour builds the item !!!
if( cProcName )
{
hb_itemDoC( cProcName, 1, ( PHB_ITEM ) pItem, 0 );
hb_itemRelease( pItem );
return hb_parnl( -1 ); // virtual machine returned numeric value !
}
else
MessageBox( 0, "inside the DLL ... One Parameter", "DOPROC", 0 );
return 123; // here you simply return the value 123
}