Использование C ++ DLL в D10 - PullRequest
       17

Использование C ++ DLL в D10

2 голосов
/ 23 февраля 2011

Я использую 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. Я пытаюсь перенести свой код, чтобы он мог работать в Delphi с поддержкой Unicode, но у меня возникла проблема.

Я прочитал документацию от 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 ]

1 голос
/ 23 февраля 2011

Я также могу опубликовать это как ответ, потому что это похоже на ответ!

Код, который вы называете кодом D6, будет отлично работать без изменений в D2010 и иметь то же значение. В Windows.pas есть две GetProcAddress перегрузки. Один из них конвертирует из Unicode в ANSI. Так что вы можете просто позвонить GetProcAddress(Handle, PChar(Proc)), как вы всегда это делали.

Волшебство выглядит следующим образом:

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;
1 голос
/ 23 февраля 2011

Вам не нужно объявлять или использовать LoadOleControlLibrary.Просто позвони старому LoadLibrary, как всегда.Важной частью кода, который вы видели, было преобразование значений UnicodeString Delphi в значения AnsiString, а затем явное приведение типа к PAnsiChar вместо PChar.(PChar - это PWideChar в настоящее время, а GetProcAddress требует не-Unicode символов.) Я предлагаю изменить ProcName, чтобы объявить его как AnsiString с самого начала.Вам понадобится меньше приведения типов.Keep LibraryName, объявленный как string.

...