我无法传递一个结构数组,但我可以传递一个。
我已经查看了这个网站上的几个答案,这些答案都被指出是正确的。但它们都不适合我。在 PInvoke 签名中答案将 IntPtr 作为“out IntPtr someName”的所有情况下,我总是得到的值为零。如果 IntPtr 是返回值,我无法将其解析为结构指针数组。
这是我使用 IntPtr 作为返回码的尝试: Unamanged C++
extern "C" EXPORTDLL_API sDeviceEndPoint **CallStartDiscovery(ZBTransport *zbTransport, int *length, int *result)
{
if(zbTransport != NULL)
{
std::list<sDeviceEndPoint *> deviceEndPoints;
sDeviceEndPoint **devEndPoints;
zbTransport->StartDiscovery(&deviceEndPoints, result);
*length = deviceEndPoints.size();
if(*length > 0)
{
devEndPoints = zbTransport->getDiscoveredEndPointPtrs();
devEndPoints[*length] = devEndPoints[0]; // Test duplicate
*length = *length + 1;
return &devEndPoints[0];
}
}
return NULL;
}
C# PInvoke 签名:
[DllImport("PInvokeBridge.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr CallStartDiscovery(IntPtr pZbTransportObject, ref int length, ref int result);
C# 实现
public Collection<DeviceEndPoint> DiscoverHCSensors()
{
Collection<DeviceEndPoint> discoveredZigBeeDevices = new Collection<DeviceEndPoint>();
int length = 0;
int result = 0;
IntPtr arrayValue = CallStartDiscovery(_pZbTransportObject, ref length, ref result);
if (ErrorCodes.ConvertResultCode(result) == ResultCode.rc_SUCCESS)
{
var deviceEndPointSize = Marshal.SizeOf(typeof(DeviceEndPoint));
for (var i = 0; i < length; i++)
{
discoveredZigBeeDevices.Add((DeviceEndPoint)Marshal.PtrToStructure(arrayValue, typeof(DeviceEndPoint)));
arrayValue = new IntPtr(arrayValue.ToInt32() + deviceEndPointSize);
}
return discoveredZigBeeDevices;
}
else
{
String error = "Error"; // Put something helpful in here
TransportException transEx = new TransportException(error);
transEx.Method = "DiscoverHCSensors";
transEx.ErrorCode = result;
transEx.TransportType = _transportString;
throw transEx;
}
}
我知道我在 C# 中定义的 DeviceEndPoint 结构的布局是正确的,因为如果我更改 C++ 代码以仅传递一个指向 DeviceEndPoint 结构的指针,我会正确加载集合中的单个结构。
另一种尝试是将值作为输出参数传递,因此在 C++ 代码中我有一个参数 sDeviceEndPoint **devs 。
我的 C# 签名是
[DllImport("PInvokeBridge.dll", CharSet = CharSet.Unicode)]
public static extern void CallStartDiscovery(IntPtr pZbTransportObject, out IntPtr devs, ref int length, ref int result);
我也尝试过 IntPtr[] devs, 'ref' 而不是 out,它们都以同样的方式失败。问题出在 C# 实现中
int result = 0;
IntPtr arrayValue = IntPTr.Zero;
CallStartDiscovery(_pZbTransportObject, out arrayValue, ref length, ref result);
arrayValue 的值始终为空 (0)。所以我在这一点之后所做的事情是无关紧要的。至少使用返回值我得到一个非空值。
据我所知,我正在做所有其他人正在做的事情。我看不出我做错了什么。否则,这是一个已在本论坛“回答”多次的问题的重复。