3

I am new to Delphi. I have a DLL with the following exported function in it:

bool __stdcall MyFunction(char * name, int * index)  

This code which calls this DLL function in C++ works perfectly:

typedef void (WINAPI * MyFunction_t)(char *, int *);
void main()
{
    HMODULE mydll = LoadLibrary(L"C:\\mydll.dll");
    MyFunction_t MyFunction = (MyFunction_t)GetProcAddress(mydll, "MyFunction");

    int index = 0;

    MyFunction("MyString", &index); 
}

I need to do the same in Delphi. Here is my code, which is not working (MyFunction gets called but the index variable doesn't receive the appropriate value). This is a code excerpt so please ignore disorder. Any input would be much appreciated!

type
  TMyFunction= function(name: PChar; var index_ptr: Integer): Boolean; stdcall;

var
  fMyFunction : TMyFunction;
  i : Integer;
  h: THandle;

begin
  Result := 0;
  h := LoadLibrary('c:\\mydll.dll');
  fMyFunction := GetProcAddress(h, 'MyFunction');
  if @fMyFunction <> nil then
  begin
    fMyFunction('MyString', i);
    Result := i;
  end;
  FreeLibrary(h);
end;
Roddy
  • 66,617
  • 42
  • 165
  • 277
Ron
  • 103
  • 1
  • 4
  • 7

2 Answers2

3

First of all I am assuming that you are using C linkage with extern "C" in case this function is defined in a C++ translation unit.

If you are using Delphi 2009 or later, you need to be aware that PChar is a pointer to a null-terminated wide character string.

To interop with your ANSI C function you need to use:

type
  TMyFunction= function(name: PAnsiChar; var index: Integer): Boolean; stdcall;

The C bool type is probably best mapped to LongBool since it's not quite the same as a Delphi Boolean:

type
  TMyFunction= function(name: PAnsiChar; var index: Integer): LongBool; stdcall;

You don't need to escape \ in strings so you can write:

h := LoadLibrary('c:\mydll.dll');

You probably ought to check for errors on the call to LoadLibrary and, technically, h is an HMODULE rather than a THandle, although that won't cause you any problems.

Idiomatic Delphi would be to write:

  if Assigned(fMyFunction) then
    fMyFunction('MyString', Result);

Basically it looks reasonable to me but I'm most suspicious of the character width.

Hope that helps.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • very good answer, I'm not too good with C/C++, but shouldn't TMyFunction be defined as TMyFunction= function(name: PAnsiChar; index: PInteger): LongBool; stdcall; since the exported function is defined as int *index? –  Jan 26 '11 at 00:44
  • @dorin that depends. If it is an optional parameter then it should be done the way you propose. Otherwise it's better as a var parameter. – David Heffernan Jan 26 '11 at 07:24
  • well the function is defined as bool __stdcall MyFunction(char * name, int * index), so I suspect name and index are mandatory, but at any rate, this goes to show you that C++ is too cryptic :-\ –  Jan 26 '11 at 07:28
  • @dorin no you can't tell from the code signature. It could be either. Take a look at a few api docs in msdn and see how some pointer parameters will be marked [in, opt], say, and others just [in]. – David Heffernan Jan 26 '11 at 07:31
  • 1
    You should write it always PAnsiChar, that works on old versions of delphi and won't need changing when/if you move up. The OP still hasn't said what version of delphi he is using. – Warren P Jan 26 '11 at 17:02
-5

Try not using STDCALL in your TMyFunction type.

Rafael Colucci
  • 6,018
  • 4
  • 52
  • 121
  • Another thing: You better allocate a Pchar variable for the input string 'MyString'. Declare a Pchar variable, set the 'MyString' string on it and pass the variable to the dll. Maybe the dll is raising a exception because of that. – Rafael Colucci Jan 25 '11 at 20:24
  • 2
    It's perfectly fine to pass a PChar this way – David Heffernan Jan 25 '11 at 20:58