I have a c++ dll which is used in a delphy pascal project and I want to create ac# project to use it. The dll returns an interface object and I am stuck right now on how to implement the C# interface to be recognized by dllImport. I have the code in pascal, that works. Also, I do not have access to the c++ source of the dll.
here is the delphy part:
interface
uses
IdGlobal;
type
// TIdBytes = array of Byte;
TBUF2 = array[0..1] of Byte;
TBUF3 = array[0..2] of Byte;
TBUF4 = array[0..3] of Byte;
PBUF4 = ^TBUF4;
TBUF6 = array[0..5] of Byte;
TBUF8 = array[0..7] of Byte;
TBUF16 = array[0..15] of Byte;
TUDPRcvRcd = record
Head: TBUF3;
DevType: Byte;
DevID: Byte;
DevIP: TBUF4;
DevMAC: TBUF6;
SoftVer: TBUF2;
HardVer: TBUF2;
DevName: TBUF16;
CHK: Byte;
end;
ReceiveDataEvent = procedure(aData: TIdBytes) of object;
ListRecive = procedure(aData: TIdBytes; aMac: PChar) of object;
ILhm = interface
function SearchDev: Integer; stdcall;
function SetRcvSearchResultProc(aReceiveDataEvent: ReceiveDataEvent ): Boolean; stdcall;
function ConnectDev(aMac, aIp, aPort, aPsd: PChar): Boolean; stdcall;
function RemoveDev(aMac: PChar): Boolean; stdcall;
function SendDataByMac(aData: TIdBytes; aMac: PChar): Boolean; stdcall;
function SetRcvDevDataProc(aListRecive: ListRecive ): Boolean; stdcall;
end;
function ControllerInit: ILhm; stdcall; external 'controller.dll' name 'ControllerInit';
implementation
end.
I wrote this in my c# project until now
[DllImport("controller.dll",
//EntryPoint = "ControllerInt", SetLastError = true,
CallingConvention = CallingConvention.Cdecl)]
public static extern ILhm ControllerInit();
public delegate object ReceiveDataEvent (byte[] aData);
public delegate object ListRecive(byte[] aData, string aMac);
public interface ILhm
{
int SearchDev();
bool SetRcvSearchResultProc(ReceiveDataEvent aReceiveDataEvent);
bool ConnectDev(string aMac, string aIp, string aPort, string aPsd);
bool RemoveDev(string aMac);
bool SendDataByMac(byte[] aData, string aMac);
bool SetRcvDevDataProc(ListRecive aListRecive);
}
I receive various errors regarding wrong definition of PInvoke or :
Additional information: The runtime has encountered a fatal error. The address of the error was at 0x7221dd74, on thread 0x305c. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.
Thanks!
Long story short - your DLL is not compatible as-is with C#.
Delphi interfaces cannot be used in C# unless:
they derive from IInterface
(known as IUnknown
in COM) and you use COM interop on the C# side.
you fake the interface on the C# side by declaring a C-style struct that contains a pointer to a vtable (an array of C-style function pointers) for the interface methods. And then you can use a pointer to that outer struct wherever the Delphi interface is expected.
Also, your two event types, ReceiveDataEvent
and ListRecive
, are using a Delphi-specific feature ( procedure of object
) that is not compatible with C# at all, so your use of delegates will not work for them. Either use C-style function pointers or a COM-style event interface.
Delphi-style dynamic arrays, like TIdBytes
, are also not compatible with C# at all, or even COM for that matter. You need to use static arrays, C-style dynamic arrays, or COM SafeArrays instead.
Also, a mistake in your code is that the DLL is using the stdcall
calling convention but your C# import is using cdecl
instead.
In short, you should really redesign the DLL before you can use it directly in C#. If that is not an option, then at least write a COM wrapper around it and then import that into C# instead.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.