在D10中使用C ++ DLL

时间:2011-02-23 15:51:59

标签: c++ delphi dllimport

我在我的应用程序中使用C ++ DLL。

type
  Tcl_bla = function(filename: PChar): Integer; cdecl;

var
  cl_bla: Tcl_bla;

function CallLibraryProc(Proc: String): Pointer;
begin
  Result := GetProcAddress(Handle, PChar(Proc));
  if not Assigned(Result) then
    Loaded := False;
  if not Loaded then
    MessageBox(0, PChar('Error => ' + Proc), 'Alert', MB_OK or MB_TOPMOST);
end;
...    
Handle := SafeLoadLibrary(
  PChar(CurrentPath + Dll),
  SEM_FAILCRITICALERRORS or SEM_NOGPFAULTERRORBOX or SEM_NOOPENFILEERRORBOX
);
if (Handle < HINSTANCE_ERROR) then
  raise Exception.Create(
    Dll + ' library can not be loaded or not found.' + SysErrorMessage(GetLastError)
  );
if Handle <> 0 then
begin
  // blabla  
  cl_bla := CallLibraryProc('cl_bla');
end;
...    
FreeLibrary(Handle);

以上代码适用于D6。我正在尝试移植我的代码,以便它可以在支持Unicode的Delphi中运行,但我遇到了麻烦。

我已阅读Embarcadero关于GetProcAddress的文档

procedure CallLibraryProc(const LibraryName, ProcName: string);
var
  Handle: THandle;
  RegisterProc: function: HResult stdcall;
begin
  Handle := LoadOleControlLibrary(LibraryName, True);
  @RegisterProc := GetProcAddress(Handle, PAnsiChar(AnsiString(ProcName)));
end;

我无法尝试这个,因为我不知道如何声明LoadOleControlLibrary!

我的CallLibraryProc可以加载DLL但不知何故cl_bla工作不正确。

我认为由于GetProcAddress的参数或我的代码问题可能是我的移植标题错误。

2 个答案:

答案 0 :(得分:1)

您无需声明或使用LoadOleControlLibrary。只需像往常一样打电话给普通老LoadLibrary。您看到的代码的重要部分是将Delphi的UnicodeString值转换为AnsiString值,然后明确地将类型转换为PAnsiChar而不是PChar。 (PChar现在为PWideCharGetProcAddress需要非Unicode字符。)我建议更改ProcName从一开始就将其声明为AnsiString。你需要更少的类型铸造。将LibraryName声明为string

答案 1 :(得分:1)

我也可以将此作为答案发布,因为它似乎就是答案!

你说的代码是D6代码在D2010中可以正常工作,并具有相同的含义。 Windows.pas中有两个GetProcAddress重载。其中一个从Unicode转换为ANSI。所以你可以像往常一样打电话给GetProcAddress(Handle, PChar(Proc))

magic 一个看起来像这样:

function GetProcAddress(hModule: HMODULE; lpProcName: LPCWSTR): FARPROC;
begin
  if ULONG_PTR(lpProcName) shr 16 = 0 then // IS_INTRESOURCE
    Result := GetProcAddress(hModule, LPCSTR(lpProcName))
  else
    Result := GetProcAddress(hModule, LPCSTR(AnsiString(lpProcName)));
end;