为了账号安全,请及时绑定邮箱和手机立即绑定

如何将结构从C#传递到C ++ DLL?

如何将结构从C#传递到C ++ DLL?

C#
蝴蝶刀刀 2021-05-18 17:18:07
好的,我的激光设备控制器的一系列问题还在继续...我想从我的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#端,我定义了函数import,如下所示:[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);这是我将LaserPointstruct实例转换为字节数组的函数: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 ++项目中使用相同的代码可以正常工作。因此,该C#互操作性代码存在该bug。有任何想法吗?
查看完整描述

2 回答

?
长风秋雁

TA贡献1757条经验 获得超7个赞

数组已经是引用类型,所以ref byte[]类似于byte**—丢失的双重间接寻址也是ref


查看完整回答
反对 回复 2021-05-23
?
一只斗牛犬

TA贡献1784条经验 获得超2个赞

如果仅打算在此处使用LaserPoint结构,则可以将函数定义为


[DllImport("..\\..\\dll\\StclDevices.dll", CallingConvention=CallingConvention.Cdecl)]

public static extern int SendFrame(UInt32 deviceIndex, LaserPoint[] pData, UInt32 numOfPoints, UInt32 scanrate);

并摆脱复制,让运行时为您做到这一点。


否则,如ildjarn所说,摆脱ref应该可以工作,因为字节数组已经是引用(指针)类型。


有关如何执行此操作的示例,PInvoke Wiki具有大多数Windows API的结构和签名,因此尽管您的调用不存在,但仍有许多类似的示例。


查看完整回答
反对 回复 2021-05-23
  • 2 回答
  • 0 关注
  • 131 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信