好的,我的激光装置控制器的一系列问题继续.我想从我的C++代码中调用DLL中的以下C#函数:
extern "C" _declspec(dllimport) int SendFrame(DWORD deviceIndex, byte* pData, DWORD numOfPoints, DWORD scanrate);指针pData指向在C++头文件中定义的激光点数组,如下所示:
#pragma pack (1)
struct LaserPoint {
WORD x;
WORD y;
byte colors[6];
};在C#方面,我将函数导入定义如下:
[DllImport("..\\..\\dll\\StclDevices.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int SendFrame(UInt32 deviceIndex, ref byte[] pData, UInt32 numOfPoints, UInt32 scanrate);..。LaserPoint结构是这样的:
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct LaserPoint {
public UInt16 x;
public UInt16 y;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public byte[] colors;
}然后,我像这样调用SendFrame函数:
LaserPoint point = new LaserPoint();
point.x = 16384;
point.y = 32768;
point.colors = new byte[] {255, 0, 0, 0, 0, 0};
byte[] arr = point2array(points);
SendFrame(0, ref arr, 1, 30000);这是我的函数,用于将LaserPoint结构实例转换为字节数组:
private static byte[] point2array(object obj) {
int len = Marshal.SizeOf(obj);
byte[] arr = new byte[len];
IntPtr ptr = Marshal.AllocHGlobal(len);
Marshal.StructureToPtr(obj, ptr, true);
Marshal.Copy(ptr, arr, 0, len);
Marshal.FreeHGlobal(ptr);
return arr;
}但我的激光装置没有收到正确的输入,因为激光的行为非常奇怪。在C++项目中使用相同的代码很好。因此,这个bug就存在于这个C#互操作性代码的某个地方。
有什么想法吗?
发布于 2018-05-02 13:53:37
数组已经是引用类型,因此ref byte[]是一个双间接方向,类似于byte** -丢失ref。
发布于 2018-05-02 14:30:46
如果只打算在这里使用LaserPoint结构,则可以将函数定义为
[DllImport("..\\..\\dll\\StclDevices.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern int SendFrame(UInt32 deviceIndex, LaserPoint[] pData, UInt32 numOfPoints, UInt32 scanrate);并摆脱复制,让运行时为您做这件事。
否则,正如ildjarn所说,摆脱ref应该有效,因为字节数组已经是引用(指针)类型。
关于如何做这些事情的例子,PInvoke维基已经为大多数的windows提供了结构和签名,所以虽然您的调用不会出现,但是也有很多类似的例子。
https://stackoverflow.com/questions/50136242
复制相似问题