Board index » delphi » !!!!!!!Need Help using Delphi DLL from MSVC!!!!!!!!!

!!!!!!!Need Help using Delphi DLL from MSVC!!!!!!!!!

[ dllprob.cpp 2K ]

I have been wrestling with the problem of calling a Delphi 2.0 DLL from
MS Visual C for several weeks now, and am ready to pull my hair out
(what is left of it). I compiled the Delphi DLL and have used it in a
Delphi program with no problem.

However when I try to access it from MS VC I run into trouble.  There
has been some discussion about this problem in several of the news
groups, and I have tried all suggestions with no success.

One of the sugestions was to develop a module definition file and to
use the LIB  with a /DEF option to create a library. The LIB function
under MS VC/C++ does not accept the /DEF option;  I tried to run LIB
by entering psatdll1.lib as the old library and psatdll1.def as the
list file, but got nowhere.

Another was to create an "ersatz" DLL in c that mimics the real Delphi
dll, and then use the newly created .lib filein my C project.  This was
soundly rejected by the linker, by telling me that it couldn't find the
correct dll.

Note that there is a  __ in front of the Delphi function.  This was also
done at the suggestion of someone in one of the disscussion groups
(I've tried it both ways - with and without __).

All of the files I've been working with are listed below.  I'd really
appreciate it if someone could set me straight.

Bill Amend.

My Delphi DLL is as follows:

{f+}
library Psatdll1;

uses
  windows,
  stdctrls,
  sysutils,
  RSTMATH in 'RSTMATH.PAS',
  PROP3CON in 'PROP3CON.PAS';

FUNCTION __PSAT(T_X: DOUBLE):DOUBLE;  cdecl; far; export; stdcall;
    VAR T_XD,P_XD,dpx : double;
    BEGIN

         T_XD := (T_X+459.6)/1.8;
         P(T_XD,P_XD);
         P_XD := P_XD/6894.76;
         __PSAT := P_XD;
    END;

    exports
__PSAT INDEX 1;

BEGIN

END.

/* My Module Definition file is listed below.*/

LIBRARY  PSAT2

EXPORTS
       WEP @1 RESIDENTNAME
       PSAT  @2
           PSAT@8=PSAT

/* My VC file to access the Delphi DLL is */

#include <windowsx.h>
#include <windows.h>
#include <dos.h>
#define DllImport _declspec(dllimport)

DllImport double PSAT(double);
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                          LPSTR lpCmdLine, int nCmdShow)

{double t,p;
t = 212.0;
p = PSAT(t);
return 0;

Quote
}

/*  My VC "ersatz" dll is */

#include <windows.h>
#define DllImport _declspec ( dllimport)
#define DllExport _declspec ( dllexport)
#define WINAPI _stdcall

extern DllExport double PSAT(double);
double   PSAT(double  temp)

{
double p;
p = 2 * temp;
return (p);

Quote
}

 

Re:!!!!!!!Need Help using Delphi DLL from MSVC!!!!!!!!!


1) Please lay off with all the !'s. Everybody has problems...

2) Does the delphi dll file work with loadlibrary?

        typedef double(WINAPI* PSTAT)(double);

        HINSTANCE hdll = LoadLibrary("psatdll1.dll");
        PSTAT pstat = (PSTAT)GetProcAddress(hdll,"__PSTAT");

  This expects that the exported name is in face "__PSTAT". To see what the
exported names are, run 'DUMPBIN /EXPORTS pstat1dll.dll'. DUMPBIN is a MSVC
tool.

3) Using 'LIB /DEF:pstat1dll.def' should work with your version of LIB. This
will only work on undecorated names (as you cannot specify a decoration scheme
in a .def file). I don't think Delphi decorates names, so this shouldn't be a
problem. In case this name decoration thing is confusing you, here I've defined
a number of variations of a function showing how the compiler decorates the
names:

Definition of a function.               Decorated Name  DLL Exported Name
-------------------------               --------------  -----------------
extern int func(int);                   ?func@@YAHH@Z   ?func@@YAHH@Z
extern int _stdcall func(int);  ?func@@YGHH@Z   ?func@@YGHH@Z
extern int _cdecl func(int);            ?func@@YAHH@Z   ?func@@YAHH@Z
extern "C" int func(int);             _func                   func
extern "C" int _stdcall func(int);    _func@4         _func@4
extern "C" int _cdecl func(int);      _func                   func

Assuming your function looks like "func" when you 'DUMBPIN /EXPORTS' the dll,
you would use a .def file along the following lines:

LIBRARY dllname
EXPORTS
        func

4) if your function looks more like '_func@4' then you will have to stub out
the functions. Your stub .cpp file would look like this:

/* stub.cpp begins */

extern "C" __declspec(dllexport) int _stdcall func(int){return 0;}

/* stub.cpp ends */

Or, if you need, you can specify a combination of .cpp and .def. (eg. if you
need to hardset the ordinals).

Take a look at mskb article Q131313 for more information. (its a VC++ article
if you search for it on the MS web site).

Hope this helps.

Chris.
--
<mailto:chr...@vironix.co.za>     |    Checkout NetFerret, a fast and easy Web
<http://www.vironix.co.za/chrisb> | search tool that searches multiple engines
Vironix Software Laboratories     |         <http://www.vironix.com/netferret>

Bill Amend <bily...@ix.netcom.com> wrote in article
<3259B00F.1...@ix.netcom.com>...

Quote
> I have been wrestling with the problem of calling a Delphi 2.0 DLL from
> MS Visual C for several weeks now, and am ready to pull my hair out
> (what is left of it). I compiled the Delphi DLL and have used it in a
> Delphi program with no problem.

> However when I try to access it from MS VC I run into trouble.  There
> has been some discussion about this problem in several of the news
> groups, and I have tried all suggestions with no success.

> One of the sugestions was to develop a module definition file and to
> use the LIB  with a /DEF option to create a library. The LIB function
> under MS VC/C++ does not accept the /DEF option;  I tried to run LIB
> by entering psatdll1.lib as the old library and psatdll1.def as the
> list file, but got nowhere.

> Another was to create an "ersatz" DLL in c that mimics the real Delphi
> dll, and then use the newly created .lib filein my C project.  This was
> soundly rejected by the linker, by telling me that it couldn't find the
> correct dll.

> Note that there is a  __ in front of the Delphi function.  This was also
> done at the suggestion of someone in one of the disscussion groups
> (I've tried it both ways - with and without __).

> All of the files I've been working with are listed below.  I'd really
> appreciate it if someone could set me straight.

> Bill Amend.

> My Delphi DLL is as follows:

> {f+}
> library Psatdll1;

> uses
>   windows,
>   stdctrls,
>   sysutils,
>   RSTMATH in 'RSTMATH.PAS',
>   PROP3CON in 'PROP3CON.PAS';

> FUNCTION __PSAT(T_X: DOUBLE):DOUBLE;  cdecl; far; export; stdcall;
>     VAR T_XD,P_XD,dpx : double;
>     BEGIN

>          T_XD := (T_X+459.6)/1.8;
>          P(T_XD,P_XD);
>          P_XD := P_XD/6894.76;
>          __PSAT := P_XD;
>     END;

>     exports
> __PSAT INDEX 1;

> BEGIN

> END.

> /* My Module Definition file is listed below.*/

> LIBRARY  PSAT2

> EXPORTS
>        WEP @1 RESIDENTNAME
>        PSAT  @2
>       PSAT@8=PSAT

> /* My VC file to access the Delphi DLL is */

> #include <windowsx.h>
> #include <windows.h>
> #include <dos.h>
> #define DllImport _declspec(dllimport)

> DllImport double PSAT(double);
> int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
>                      LPSTR lpCmdLine, int nCmdShow)

> {double t,p;
> t = 212.0;
> p = PSAT(t);
> return 0;
> }

> /*  My VC "ersatz" dll is */

> #include <windows.h>
> #define DllImport _declspec ( dllimport)
> #define DllExport _declspec ( dllexport)
> #define WINAPI _stdcall

> extern DllExport double PSAT(double);
> double   PSAT(double  temp)

> {
> double p;
> p = 2 * temp;
> return (p);
> }

Re:!!!!!!!Need Help using Delphi DLL from MSVC!!!!!!!!!


Quote
Bill Amend wrote:

> I have been wrestling with the problem of calling a Delphi 2.0 DLL from
> MS Visual C for several weeks now, and am ready to pull my hair out
> (what is left of it). I compiled the Delphi DLL and have used it in a
> Delphi program with no problem.

> However when I try to access it from MS VC I run into trouble.  There
> has been some discussion about this problem in several of the news
> groups, and I have tried all suggestions with no success.

> Bill Amend.

> My Delphi DLL is as follows:

> {f+}
> library Psatdll1;

> uses
>   windows,
>   stdctrls,
>   sysutils,
>   RSTMATH in 'RSTMATH.PAS',
>   PROP3CON in 'PROP3CON.PAS';

> FUNCTION __PSAT(T_X: DOUBLE):DOUBLE;  cdecl; far; export; stdcall;
>     VAR T_XD,P_XD,dpx : double;
>     BEGIN

>          T_XD := (T_X+459.6)/1.8;
>          P(T_XD,P_XD);
>          P_XD := P_XD/6894.76;
>          __PSAT := P_XD;
>     END;

>     exports
> __PSAT INDEX 1;

> BEGIN

> END.

> /* My Module Definition file is listed below.*/

> LIBRARY  PSAT2

> EXPORTS
>        WEP @1 RESIDENTNAME
>        PSAT  @2
>            PSAT@8=PSAT

> /* My VC file to access the Delphi DLL is */

> #include <windowsx.h>
> #include <windows.h>
> #include <dos.h>
> #define DllImport _declspec(dllimport)

> DllImport double PSAT(double);
> int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
>                           LPSTR lpCmdLine, int nCmdShow)

> {double t,p;
> t = 212.0;
> p = PSAT(t);
> return 0;
> }

> /*  My VC "ersatz" dll is */

> #include <windows.h>
> #define DllImport _declspec ( dllimport)
> #define DllExport _declspec ( dllexport)
> #define WINAPI _stdcall

> extern DllExport double PSAT(double);
> double   PSAT(double  temp)

> {
> double p;
> p = 2 * temp;
> return (p);
> }

I believe your problem may be the different calling conventions that MS
and Borland use when dealing with floating point parameters and function
results. From previous posts and personal experience, you can pass
pointers to floating point parameters between DLL's and MS C/C++, but
not pass floating point by value. Forget about returning floating point
function results.

Try temporarily changing the parameters and function result to integers
and see it works to confirm my hypothesis. If it works change the code
to pass pointers to the floating point values.

Regards,

--
----------------------------------------------------------------------------
     Dr. Harley Mackenzie                          Email: h...@world.net
     Principal Operations Research Analyst
     Yallourn Energy                               Tel: +61 3 9207 7719
     9 Floor / 114 William Street                  Fax: +61 3 9606 0742
     Melbourne 3000, Australia
     PGP fingerprint = BC 53 BE 16 43 C5 BB 50  B7 9F 3D D8 49 CA 0C A0
----------------------------------------------------------------------------

Re:!!!!!!!Need Help using Delphi DLL from MSVC!!!!!!!!!


On Mon, 07 Oct 1996 18:36:15 -0700, Bill Amend <bily...@ix.netcom.com>
wrote:

Hi,

I have no C++ here to do anything useful for you, but I find this to
be a bit strange....

Quote
>FUNCTION __PSAT(T_X: DOUBLE):DOUBLE;  cdecl; far; export; stdcall;

What do you want:
cdecl or stdcall.
decide and only use one (preferably stdcall).

Hope this helps

Meikel Weber
m.we...@public.ndh.com
Make sure you visit my homepage
http://ourworld.compuserve.com/Homepages/meikel/mew.htm

Re:!!!!!!!Need Help using Delphi DLL from MSVC!!!!!!!!!


Quote
Chris Becke wrote:

> 1) Please lay off with all the !'s. Everybody has problems...

> 2) Does the delphi dll file work with loadlibrary?

>         typedef double(WINAPI* PSTAT)(double);

>         HINSTANCE hdll = LoadLibrary("psatdll1.dll");
>         PSTAT pstat = (PSTAT)GetProcAddress(hdll,"__PSTAT");

>   This expects that the exported name is in face "__PSTAT". To see what the
> exported names are, run 'DUMPBIN /EXPORTS pstat1dll.dll'. DUMPBIN is a MSVC
> tool.

> 3) Using 'LIB /DEF:pstat1dll.def' should work with your version of LIB. This
> will only work on undecorated names (as you cannot specify a decoration scheme
> in a .def file). I don't think Delphi decorates names, so this shouldn't be a
> problem. In case this name decoration thing is confusing you, here I've defined
> a number of variations of a function showing how the compiler decorates the
> names:

> Definition of a function.               Decorated Name  DLL Exported Name
> -------------------------               --------------  -----------------
> extern int func(int);                   ?func@@YAHH@Z   ?func@@YAHH@Z
> extern int _stdcall func(int);  ?func@@YGHH@Z   ?func@@YGHH@Z
> extern int _cdecl func(int);            ?func@@YAHH@Z   ?func@@YAHH@Z
> extern "C" int func(int);               _func                   func
> extern "C" int _stdcall func(int);      _func@4         _func@4
> extern "C" int _cdecl func(int);        _func                   func

> Assuming your function looks like "func" when you 'DUMBPIN /EXPORTS' the dll,
> you would use a .def file along the following lines:

> LIBRARY dllname
> EXPORTS
>         func

> 4) if your function looks more like '_func@4' then you will have to stub out
> the functions. Your stub .cpp file would look like this:

> /* stub.cpp begins */

> extern "C" __declspec(dllexport) int _stdcall func(int){return 0;}

> /* stub.cpp ends */

> Or, if you need, you can specify a combination of .cpp and .def. (eg. if you
> need to hardset the ordinals).

> Take a look at mskb article Q131313 for more information. (its a VC++ article
> if you search for it on the MS web site).

> Hope this helps.

> Chris.

Chris

You seem to know your way around DLL / C++ conflicts. I'm having (what
should really be only a) minor problem porting a working 16 bit program
into it's 32 bit counterpart with respect to LoadLibrary and
GetProcAddress. I've set up a special framework class to 'try' and
handle this for me. Ideally I want to load a 32 bit Microsoft Fortran
DLL. The Fortran I've set up has one single external function 'EXECUTE'
as I've decided to share all parameters via Fortrans native interface,
"FILES". At any rate, the 16 bit version loads the DLL and calls the
desired function fine, the 32 bit however seems to load fine and pass
back an address. Unfortunately when you trace into it, there is nothing
there except a bunch of zeros.
Here's a previous posting:

-------------------------------------------------------------------------------------

URGENT: Need that sample program on calling functions in 32-bit DLL
EXPLICITLY using LoadLibrary/GetProcAddress.

I have a situation where I have to access a Fortran developed

mathematical model into it's corresponding C++ framework. Needless to

say the FORTRAN is Microsoft's, the C++ Framework developed under

Borland 4.53.

Under 16 bit, a framework was developed to handle the loading of any

given DLL and EXPLICITlty calling a routine from the DLL via a call to

'GetProcAddress'. This works fine in my 16 bit world. The trouble is

that I now have 'Borland 5.01 with Design Tools' and yes I WANT to use

it.

When I port to the 32 bit world everything seems to come over quite fine

but I'm having a wicked time with the address returned from

'GetProcAddress'. While the value seems reasonable, when it gets called,

the de{*word*81} stops the process saying that the thread has generated an

access violation. When I look at the resulting code all I get is this

block of nulls (or na-na land). It seems to have either jumped into a

place where it should not have or there is code suppose to be there that

aint.

Has anybody, anywhere in there software respositories an C++, SDK or WIN

32 API example of a LoadLibrary / GetProcAddress call demonstrating an

EXPLICIT call to a DLL function (with or without parameters) working in

a 32 bit environment.

Here's the code for a (hopefully better idea as to what I'm after).

This really shouldn't be that hard to do and is CRITICAL to my going

about this like I want to and should be about to.

===============================================

-------- StdLinkLibWin Framework code ---------

Remember, this works fine in 16 bit

-----------------------------------------------

void StdLinkLibWin::Load()

{

        heap DWORD hn = 0;

   // SetErrorMode(SEM_NOOPENFILEERRORBOX);

   if ( !IsLoaded() ) {

      iw_HInst = (word) LoadLibrary( GetLib().GetStr() );

      if ( iw_HInst > (word)HINSTANCE_ERROR ) {

         SetStatus( 0 );

         SetLoaded( true );

      }

      else {

        hn = GetLastError();

         SetStatus( (word)hn );

         throw StdLinkLib::BadLoad();

      }

   }

Quote
}

void StdLinkLibWin::Free()

{

   if ( IsLoaded() )

      if ( iw_HInst > (word)HINSTANCE_ERROR )

         FreeLibrary( (HINSTANCE)iw_HInst );

   iw_HInst = 0;

   SetLoaded( false );

Quote
}

----- Pay paticular attention to the line defining 'lpfn_LibRtn' and the

----- '(FARPROC)' cast. It's my best guess as to why this isn't working

----- but there again, your the expert.

void StdLinkLibWin::Call( const char* poc )

{

   heap int (FAR *lpfn_LibRtn) ();

   heap HMODULE hw = (HMODULE) iw_HInst;

   (FARPROC) lpfn_LibRtn = GetProcAddress( hw, poc );

    if ( !lpfn_LibRtn )

      throw BadCall();

   else {

      DirEntry dt_Old, dt_New( GetDir() );

      dt_Old.ToAbs();

      if ( IsUseDir() )

         dt_New.SetCWD();

      SetStatus( (*lpfn_LibRtn)() );

      if ( IsUseDir() )

         dt_Old.SetCWD();

   }

Quote
}

==============================================================================

--- The following is the test code I use to set up and test the

Framework ----

void TestLoadLib()

{

   heap StdLinkLibWin ht( "models\\LdrFrmWk\\noname.dll", false ), ht2(

ht );

   if ( ht == ht2 )

      ;

   ht = ht2;

   if ( ht == ht2 )

      ;

   try {

      StdLinkLib *pdt = new StdLinkLibWin(

"MODELS\\YASSIM11\\yassim32.dll" );

   //   pdt->Free();

      delete pdt;

        StdLinkLibWin ht3( "MODELS\\YASSIM11\\yassim32.dll" );

//      ht3.Load();

      ht3.Call( "EXECUTE" );

      if ( ht3.GetStatus() == 7 ) {

         StdLinkLibWin dt( "MODELS\\YASSIM11\\yassim32.dll" );

         dt.Call( "EXECUTE" );

         dt.Call( "EXECUTE" );

         dt.Call( "EXECUTE" );

         dt.Call( "EXECUTE" );

         for ( int di=0; di<20; di++)

            dt.Call( "EXECUTE" );

         if ( dt.GetStatus() == 0 ) {

            dt.Free();

            dt.Load();

            dt.Call( "MUL" );

         }

      }

   }

   catch ( StdLinkLib::Error ) {

      cout << "StdLinkLib::Error" << endl;

   }

   catch ( ... ) {

      cout << "Something else went wrong" << endl;

   }

Quote
}

=======================================================================================

--- The following is the DEF file used by Developer Studio to generate

the 32 bit DLL

--- Maybe I'm suppose to specify STACKSIZE or something, I just don't

have an reasonable

--- example to go by.

;

; The LIBRARY statement below 'MUST' be the the name of the resulting

DLL.

;

; Use the DESCRIPTION field to provide information concerning

; identification and version control.

;

; Comment out the EXECUTE line and uncomment the RUN line if you wish to

use

; the SUBROUTINE approach as mentined in LDRFRMWK.FOR.

;

; Dont change anything else unless you know what your at.

;

LIBRARY     YASSIM32

DESCRIPTION 'SPS YasSim 1.1 (32-Bit) - CORETEC Adaptive Model -  0x0110'

CODE        PRELOAD MOVEABLE DISCARDABLE

DATA        PRELOAD MOVEABLE SINGLE

HEAPSIZE    1024

EXPORTS

            EXECUTE

==============================================================================================

Like I said, I think the best way you might be able to help me is to

send me a short example

a DLL function being EXPLICITLY called (as opposed to IMPLICITly via the

_export/_import/.lib

approach.

Could really use your help. This seems so simple and therefore is

driving me nuts becouse I

can't get it to work.

Thanks in advance.

------------------------------------------------------------------------------------

Chris,

The best work around I've come up with to date is to either try to do a
IMPLICIT link or consider the purchase of Visual C++ (which will
probably become a reality in any regard). However, I don't like work
arounds. If there is anything you can do, it would much appreciated.

Thanks in advance.

------------------------------------------------------------------------
Perry S. Anderson
Senior Systems Analyst
CORETEC Incorporated
mailto:core...@voyager.newcomm.net
http://www.newcomm.net/coretec
=========================================

Other Threads