德尔福动态DLL调用中的奇怪行为

Strange behaviour in Delphi dynamic DLL call

本文关键字:动态 DLL 调用 德尔福      更新时间:2023-10-16

我有以下问题:

我有一个用 C++ 编写的 DLL,它接受输入参数作为 * 字符。

通过以下方式使用 Delphi RTL 声明 DLL 时:

function MyDllCall(aParam: PAnsiChar): Longint; stdcall; external 'MyDllName.dll' name 'MyFunction'

并从我的代码中调用它:

MyDllCall(PAnsiChar('some text'));

它工作得很好。

当我尝试通过调用LoadLibrary,GetProcAddress和FreeLibrary来调用它时,如下面的代码:

procedure DllCall;
type
  TMyDllCall = function(aParam: PAnsiChar): Longint;
var
  aMyDllCall: TMyDllCall;
  libHandle: Integer;
  res: Integer; 
begin
  libHandle := LoadLibrary('MyDLL.dll');
  if libHandle <> 0 then
  begin
    @aMyDllCall := GetProcAddress(libHandle, 'MyDllFunction');
    if @aMyDllCall <> nil then
    begin
      res:= aMyDllCall(PAnsiChar('some text')); << This crashes
      FreeLibrary(libHandle);
    end;
  end;
end;

我相信这个问题与作为 PAnsiChar 传递的字符串参数有关。尝试更改C++ dll 源代码注销参数,并验证分配的参数变量中的一些奇怪文本。

编辑:以下是C++ Dll代码的一部分:

#include "stdafx.h"
#pragma once  
#define MYDLLLIBRARY_API extern "C" __declspec(dllexport)   
MYLIBRARY_API DWORD WINAPI MyDllFunction(char * dirname);
DWORD WINAPI MyDllFunction(char * dirName){
    return someFunction(dirName);
}
void getFileNames(char * workingDir){
    HANDLE hFind;
    WIN32_FIND_DATAA data;
    char nextfilename[260];
    sprintf(nextfilename, "%s*.jpg", workingDir);
    hFind = FindFirstFileA(nextfilename, &data);
    if (hFind != INVALID_HANDLE_VALUE) {
        do {
            if (strlen(data.cFileName) < 3) continue;
            char tmp[260];
            sprintf(tmp, "%s%s",workingDir, data.cFileName);
            filenames.push_back(tmp);
        } while (FindNextFileA(hFind, &data));
        FindClose(hFind);
    } else{
        exit(0);
    }
}
int MyDllFunction(char* workingDir)
{
    ...
    getFileNames(workingDir);
    ...
}

我错过了什么吗?谢谢。

您的第一个定义(静态定义)使用stdcall

function MyDllCall(aParam: PAnsiChar): Longint; stdcall; external Stdcall 'MyDllName.dll' name 'MyFunction';

你的第二个(动态)没有。由于这是失败的,我认为很明显,缺少stdcall是问题所在:

type
  TMyDllCall = function(aParam: PAnsiChar): Longint;  // No stdcall here