c# – 使用带有P / Invoke的ref struct或类
发布时间:2020-12-15 07:51:40 所属栏目:百科 来源:网络整理
导读:我知道这个问题已在这里多次讨论,但我无法找到适合我具体情况的答案. 我需要在C#中调用一个非托管的C方法,它接受一个struct对象的指针(我不会流利地说C: int doStuff(MYGRID* grid,int x); 但结构本身引用了另一个结构对象: struct MYGRID { int hgap; int
我知道这个问题已在这里多次讨论,但我无法找到适合我具体情况的答案.
我需要在C#中调用一个非托管的C方法,它接受一个struct对象的指针(我不会流利地说C: int doStuff(MYGRID* grid,int x); 但结构本身引用了另一个结构对象: struct MYGRID { int hgap; int vgap; MYIMAGE* image; } struct MYIMAGE { int res; int width; int height; } 而且我还需要像这样直接设置图像指针: MYGRID* pGrid = new MYGRID; MYIMAGE* pImage = new MYIMAGE; pGrid->image = pImage; 所以,我的问题是:在C#代码中,我应该使用“struct”对象并通过“ref”传递它,就像P / Invoke Interop Assistant建议我一样吗?这意味着以下代码: MyGrid myGrid = new MyGrid(); MyImage myImage = new MyImage(); myGrid.image = Marshal.AllocHGlobal(Marshal.SizeOf(image)); // A IntPtr in my struct myGrid.image = Marshal.StructureToPtr(image,myGrid.image,false); doStuff(ref myGrid,0); 或者我可以使用“class”而不是“struct”来获得以下非常简单的代码: MyGrid myGrid = new MyGrid(); MyImage myImage = new MyImage(); myGrid.image = myImage; doStuff(myGrid,0); 在第一种情况下,我在结构MyGrid中使用“IntPtr”,在第二种情况下只使用MyImage对象. 解决方法
不要将C#struct与C struct混淆.它们不是同一件事. C#结构用于声明值类型.在另一种类型中聚合值类型时,将其直接存储在包含的实例中,而不是存储对存储在堆上的实例的引用. C结构只是一个默认情况下所有成员都是公共的类.
在您的情况下,因为MYGRID包含指向MYIMAGE的指针,所以您应该像第二个示例中那样使用类.但是,应删除myGrid参数的引用. 下面是我测试的一些示例代码. C代码: #include "windows.h" struct MYIMAGE { int res; int width; int height; }; struct MYGRID { int hgap; int vgap; MYIMAGE* image; }; extern "C" __declspec(dllexport) int doStuff(MYGRID* grid,int x) { return 0; } 声明C#类和外部函数: [StructLayout(LayoutKind.Sequential)] class MyGrid { public int hgap; public int vgap; public IntPtr image; } [StructLayout(LayoutKind.Sequential)] class MyImage { public int res; public int width; public int height; } [DllImport("MyDll")] static extern int doStuff(MyGrid grid,int x); 调用外部函数: MyImage image = new MyImage(); MyGrid grid = new MyGrid(); grid.image = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MyImage))); Marshal.StructureToPtr(image,grid.image,false); doStuff(grid,0); 如果在C#项目中打开非托管调试,则可以使用调试器进入C函数并验证类是否已正确编组. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |