I have a 3rd party DLL written in Delphi (no source code) that I need to call from C#. I also have a second DLL also written in Delphi (with source code) that calls the functions and procedures in the 3rd party DLL and exports those calls.
I can call the second DLL from C# to call indirectly to the functions and procedures in the first DLL, but there are (seemingly) random Access Violations in the second DLL, so I’d like to access the first DLL directly from C#.
An example of the exported code in the second Dll is:
type // Types used to cast function returns from GetProcAddress
SetCommsDebugProc = procedure(DebugOnOff: boolean);
var // function pointers used when assigning GetProcAddress
pSetCommsDebugProc: SetCommsDebugProc = nil;
function AttachComms(Handle: HWND; timeCount: Integer; simMode: Boolean): Boolean;
const
FunctName = 'AttachComms';
var
RC: Boolean;
begin
RC := FALSE;
if (_hThirdPartyWin32Dll <> 0) then
begin
if not assigned(pAttachCommsProc) then
pAttachCommsProc := GetProcAddress(_hThirdPartyWin32Dll, pansichar(FunctName)); // get the address
if assigned(pAttachCommsProc) then
begin
RC := pAttachCommsProc(Handle, timeCount, simMode); // call the function
end
else
raise Exception.create('Unable to load ' + FunctionName + ' from ' + DLL_NAME + '.Dll');
end;
result := RC;
end;
Another example that has no return value is:
type // Types used to cast function returns from GetProcAddress
AttachCommsProc = function(Handle: HWND; timeCount: Integer; simMode: Boolean): Boolean;
var // function pointers used when assigning GetProcAddress
pSetCommsDebugProc: SetCommsDebugProc = nil;
procedure SetCommsDebug(DebugOnOff: boolean); stdcall;
const
FunctName = 'SetCommsDebug';
begin
if (_hThirdPartyWin32Dll <> 0) then
begin
if not assigned(pSetCommsDebugProc) then
pSetCommsDebugProc := GetProcAddress(_hThirdPartyWin32Dll, pansichar(FunctName)); // get the address
if assigned(pSetCommsDebugProc) then
begin
pSetCommsDebugProc(DebugOnOff); // call the function
end
else
raise Exception.create('Unable to load ' + FunctionName + ' from ' + DLL_NAME + '.Dll');
end;
end;
I've tried [DllImport]
and [UnmanagedFunctionPointer]
but with limited success. I've also tried several of the answers to similar questions here in StackOverflow.
Sometimes I get a PInvokeUnbalanceStackException
, and sometimes it just hangs.
I'm using Windows 10, MSVS 2017 Enterprise, Delphi 10 Community
An example of the SecondDll [DllImport]
that works is:
[DllImport("Second.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void SetCommsDebug(bool onoff);
I tried the same code with the 3rd party DLL and with all combinations of CharSet
and CallingConvention
.
The [UnmanagedFunctionPointer]
attempt was based on the Dynamic version in an answer to this question.
Unfortunately, I'm not able to post a Minimal, Complete, and Verifiable Example because of an NDA with the 3rd party, and it would be too big to comprehend.
Comments
Post a Comment