Reputation: 681
I use a C++ DLL in my app.
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);
The codes aboves works fine with D6. I'm trying to port my code so it can run in Delphi with Unicode support but I have a trouble.
I've read the documentation from Embarcadero about 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;
I can't try this because I don't know how to declare LoadOleControlLibrary!
My CallLibraryProc can load the DLL but somehow cl_bla works incorrectly.
I think the problem with my code because of GetProcAddress's parameter or.. maybe my ported header is wrong.
Upvotes: 2
Views: 536
Reputation: 612844
I may as well post this this as an answer, because it seems like the answer!
The code that you say is D6 code will work fine unmodified in D2010, and have the same meaning. There are two GetProcAddress
overloads in Windows.pas. One of them converts from Unicode to ANSI. So you can just call GetProcAddress(Handle, PChar(Proc))
just like you always did.
The magic one looks like this:
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;
Upvotes: 1
Reputation: 163257
You don't need to declare or use LoadOleControlLibrary
. Just call plain old LoadLibrary
like you always have. The important part of the code you saw was to convert Delphi's UnicodeString
values into AnsiString
values, and then type-cast explicitly to PAnsiChar
instead of PChar
. (PChar
is PWideChar
nowadays, and GetProcAddress
requires non-Unicode characters.) I suggest changing ProcName
to declare it as an AnsiString
from the beginning. You'll need less type-casting. Keep LibraryName
declared as string
.
Upvotes: 1