在Delphi中使用指针调用DLL函数

3

我是Delphi的新手。 我有一个DLL,其中包含以下导出函数:

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

这段调用DLL函数的C++代码可以正常运行:
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); 
}

我需要在Delphi中完成同样的操作。以下是我的代码,但不起作用(MyFunction被调用了,但索引变量没有得到适当的值)。以下是代码片段,请忽略无序情况。如有任何建议,请提出!

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;

你的 DLL 是用哪种语言构建的? - Rafael Colucci
1
你的 C 代码调用了一个“void”函数,但 Delphi 代码调用了一个返回布尔值的函数...? - Roddy
@Roddy 这是调用函数的 C 代码中的问题,但似乎是无害的,因为这段代码没有使用返回值。 - David Heffernan
2个回答

3

首先,我假定您在 C++ 翻译单元中使用 C 语言链接并带有 extern "C"

如果您使用的是 Delphi 2009 或更高版本,则需要注意 PChar 是指向以 null 结尾的宽字符字符串的指针。

要与您的 ANSI C 函数进行交互,您需要使用:

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

C语言中的bool类型最好映射到LongBool,因为它与Delphi的Boolean并不完全相同:

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

在字符串中,您不需要转义\,因此可以这样编写:

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

您可能需要检查调用LoadLibrary时是否有错误,从技术上讲,h是一个HMODULE而不是THandle,虽然这不会给您带来任何问题。

Delphi的惯用写法应该是:

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

基本上,对我来说看起来合理,但我最怀疑的是字符宽度。

希望这有所帮助。


非常好的答案,我对C/C++不是很熟悉,但是导出函数被定义为int *index,TMyFunction不应该被定义为TMyFunction= function(name: PAnsiChar; index: PInteger): LongBool; stdcall;吗? - user497849
@dorin 这取决于具体情况。如果这是一个可选参数,那么应该按照您提出的方式进行。否则最好将其作为 var 参数。 - David Heffernan
好的,该函数定义为bool __stdcall MyFunction(char * name, int * index),因此我怀疑name和index是必需的,但无论如何,这表明C++太晦涩难懂了。:-\ - user497849
@dorin 不,你无法从代码签名中判断。它可能是任何一种情况。看看 MSDN 中的一些 API 文档,看看一些指针参数是如何标记为 [in,opt],而其他一些只是 [in]。 - David Heffernan
1
你应该总是写成 PAnsiChar,这在旧版本的 Delphi 上可以工作,并且在升级时不需要更改。但是,OP 仍然没有说他正在使用哪个版本的 Delphi。 - Warren P

-5

尝试在TMyFunction类型中不使用STDCALL。


另外一件事:你最好为输入字符串'MyString'分配一个Pchar变量。声明一个Pchar变量,将'MyString'字符串设置在其中,并将该变量传递给dll。也许dll是因为这个原因引发了异常。 - Rafael Colucci
2
这种方式传递PChar是完全可以的。 - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接