从 Pascal 到 C# 的代码翻译
Code translation from pascal to c#
我有一个在 delphy pascal 项目中使用的 c++ dll,我想创建一个 c# 项目来使用它。
dll returns 一个接口对象,我现在被困在如何实现 dllImport 识别的 C# 接口上。我有 pascal 的代码,可以用。另外,我无权访问 dll 的 c++ 源代码。
这是德尔菲部分:
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.
到目前为止,我在我的 c# 项目中写过这个
[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);
}
我收到关于 PInvoke 错误定义的各种错误或:
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.
谢谢!
长话短说 - 您的 DLL as-is 与 C# 不兼容。
Delphi 接口不能在 C# 中使用,除非:
它们派生自 IInterface
(在 COM 中称为 IUnknown
)并且您在 C# 端使用 COM 互操作。
你通过声明一个 C-style 结构来伪造 C# 端的接口,该结构包含一个指向接口方法的 vtable(C-style 函数指针的数组)的指针.然后您可以在需要 Delphi 接口的任何地方使用指向该外部结构的指针。
此外,您的两个事件类型 ReceiveDataEvent
和 ListRecive
使用的 Delphi-specific 功能 (procedure of object
) 与 C# 完全不兼容,所以您对代表的使用对他们不起作用。使用 C-style 函数指针或 COM-style 事件接口。
Delphi-style 动态数组,如 TIdBytes
,也不与 C# 兼容,甚至与 COM 不兼容。您需要改用静态数组、C-style 动态数组或 COM SafeArrays。
此外,您的代码中的一个错误是 DLL 使用的是 stdcall
调用约定,但您的 C# 导入使用的是 cdecl
。
总之,你真的应该重新设计DLL,然后才能在C#中直接使用它。如果这不是一个选项,那么至少围绕它编写一个 COM 包装器,然后将其导入 C#。
我有一个在 delphy pascal 项目中使用的 c++ dll,我想创建一个 c# 项目来使用它。 dll returns 一个接口对象,我现在被困在如何实现 dllImport 识别的 C# 接口上。我有 pascal 的代码,可以用。另外,我无权访问 dll 的 c++ 源代码。
这是德尔菲部分:
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.
到目前为止,我在我的 c# 项目中写过这个
[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);
}
我收到关于 PInvoke 错误定义的各种错误或:
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.
谢谢!
长话短说 - 您的 DLL as-is 与 C# 不兼容。
Delphi 接口不能在 C# 中使用,除非:
它们派生自
IInterface
(在 COM 中称为IUnknown
)并且您在 C# 端使用 COM 互操作。你通过声明一个 C-style 结构来伪造 C# 端的接口,该结构包含一个指向接口方法的 vtable(C-style 函数指针的数组)的指针.然后您可以在需要 Delphi 接口的任何地方使用指向该外部结构的指针。
此外,您的两个事件类型 ReceiveDataEvent
和 ListRecive
使用的 Delphi-specific 功能 (procedure of object
) 与 C# 完全不兼容,所以您对代表的使用对他们不起作用。使用 C-style 函数指针或 COM-style 事件接口。
Delphi-style 动态数组,如 TIdBytes
,也不与 C# 兼容,甚至与 COM 不兼容。您需要改用静态数组、C-style 动态数组或 COM SafeArrays。
此外,您的代码中的一个错误是 DLL 使用的是 stdcall
调用约定,但您的 C# 导入使用的是 cdecl
。
总之,你真的应该重新设计DLL,然后才能在C#中直接使用它。如果这不是一个选项,那么至少围绕它编写一个 COM 包装器,然后将其导入 C#。