-1

我在(stdcall)DLL 中有一些函数,它们采用函数指针来执行回调。

该方法DeviceStateChangedNotifyCardDataStateChangedNotify接受Long回调地址的参数。

这是一个 VB6 示例:

Declare Sub DeviceStateChangedNotify Lib "Device.dll" (ByVal lpFunc As Long)
Declare Sub CardDataStateChangedNotify Lib "Device.dll" (ByVal lpFunc As Long)

Public Sub SetupCallBacks()
     Call DeviceStateChangedNotify(AddressOf OnEventDeviceStateChanged)
     Call CardDataStateChangedNotify(AddressOf OnEventCardDataStateChanged)
End Sub

Public Sub OnEventDeviceStateChanged(ByVal parm As Long)
    ...
End Sub

Public Sub OnEventCardDataStateChanged(ByVal parm As Long)
    ...
End Sub

我如何在 C# 中做到这一点?

我试图创建一个具有相同方法签名的委托,OnEventDeviceStateChangedOnEventCardDataStateChanged似乎不起作用:

delegate void DeviceStateChanged(long parm);
DeviceStateChanged stateChanged = EventDeviceStateChanged;
CardDataStateChangedNotify(stateChanged);

这会在最后一行产生语法错误:

无法从“DeviceStateChanged”转换为“long”

4

2 回答 2

3

你很亲密。

是的,您需要创建一个委托以匹配回调函数签名,然后更改 DLL 函数声明以将该委托用于函数指针参数。然后,P/Invoke 将根据需要对其进行编组并将有效指针传递给函数。

[DllImport("Device.dll")]
private static extern void DeviceStateChangedNotify(DeviceStateChangedDelegate Func);

private delegate void DeviceStateChangedDelegate(Int32 parm);

private void OnDeviceStateChanged(Int32 parm) {
  ...
}

当需要传递时,直接传递函数即可:

DeviceStateChangedNotify(OnDeviceStateChanged);

请注意,由于 .NET 应用程序(默认情况下)与架构无关(将根据系统架构以 32 位或 64 位运行),因此您需要确保您的 DLL 和目标架构匹配。

如果您只有一个 32 位 DLL,那么您需要将您的 .NET 项目设置为以 x86 为目标。

如果您有 32 位和 64 位 DLL,那么您可以将 .NET 项目设置为任何目标,但您需要检查 DLL 回调是使用 32 位整数(C++DWORD等)还是系统整数(C++ int)。如果它确实使用系统整数,那么您需要更新您的委托和回调函数以使用IntPtr而不是intor Int32

于 2013-06-06T10:01:40.230 回答
1

您需要声明您的 p/invoke 代码,以便它接收委托而不是long. 在 VB6 中,无法指定委托甚至指针,因此无法使用整数和AddressOf.

另一个问题是 VB6Long是 32 位的,所以要匹配你需要使用 C# int。那是因为 C#long是 64 位的。

因此,在 C# 中,您可以这样做:

delegate void DeviceStateChanged(int parm);

[DllImport(@"Device.dll")]
static extern void DeviceStateChangedNotify(DeviceStateChanged lpFunc);

[DllImport(@"Device.dll")]
static extern void CardDataStateChangedNotify(DeviceStateChanged lpFunc);

当然,您需要调整回调函数以匹配委托的新定义。

就是这样!

于 2013-06-06T09:56:10.817 回答