将包含数组的 C 结构编组到 C#
在 stackoverflow 社区的大力帮助下,我成功调用了本机 DLL 函数。但是,我无法修改 ID
或 intersects
数组的值。无论我在 DLL 端如何处理它,旧值都会保留。似乎是只读的。
以下是一些代码片段:
C++ 结构体:
typedef struct _Face {
int ID;
int intersects[625];
} Face;
C# 映射:
[StructLayout(LayoutKind.Sequential)]
public struct Face {
public int ID;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 625)]
public int[] intersects;
}
C++ 方法(在 VS2010 中类型设置为 DLL):
extern "C" int __declspec(dllexport) __stdcall
solve(Face *faces, int n){
for(int i =0; i<n; i++){
for(int r=0; r<625; r++){
faces[i].intersects[r] = 333;
faces[i].ID = 666;
}
}
C# 方法签名:
[DllImport("lib.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern int solve(Face[] faces, int len);
C# 方法调用:
Face[] faces = new Face[10];
faces[0].intersects = new int[625];
faces[0].ID = -1; //.. and add 9 more ..
solve(faces, faces.Length);
// faces[0].ID still equals -1 and not 666
最诚挚的问候, e.
With great help of the stackoverflow community, I've managed to call a native DLL function. However, I can't modify the values of ID
or intersects
array. No matter what I do with it on the DLL side, the old value remains. It seems read-only.
Here are some code fragments:
C++ struct:
typedef struct _Face {
int ID;
int intersects[625];
} Face;
C# mapping:
[StructLayout(LayoutKind.Sequential)]
public struct Face {
public int ID;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 625)]
public int[] intersects;
}
C++ method (type set to DLL in VS2010):
extern "C" int __declspec(dllexport) __stdcall
solve(Face *faces, int n){
for(int i =0; i<n; i++){
for(int r=0; r<625; r++){
faces[i].intersects[r] = 333;
faces[i].ID = 666;
}
}
C# method signature:
[DllImport("lib.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern int solve(Face[] faces, int len);
C# method invocation:
Face[] faces = new Face[10];
faces[0].intersects = new int[625];
faces[0].ID = -1; //.. and add 9 more ..
solve(faces, faces.Length);
// faces[0].ID still equals -1 and not 666
Kindest regards,
e.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您必须明确告诉 pinvoke 编组器该数组需要被编回。您可以使用 [In] 和 [Out] 属性来执行此操作。像这样:
You have to tell the pinvoke marshaller explicitly that the array needs to be marshaled back. You do this with the [In] and [Out] attributes. Like this:
这只是一个输出字段?为了深入了解这一点,我尝试用足够大的 byte[] 替换您的 Face[] 参数,并查看字节数组是否填充了任何内容(您必须稍微更改您的 [DllExport] )。
另外,我在使用 char* 执行此操作时遇到的另一件事是我必须在 C# 中预先分配缓冲区。例如:
不起作用。但假设返回的 theString 最多为 256 个字符,我会这样做:
而且我会做生意。我建议尝试 byte[] 替换,如果这不起作用,请尝试预分配的字节数组。一旦您看到字节数组实际上被您的 C++ 代码更改,您就可以弄清楚如何将其编组到您的 C# 结构中。
This is an output field only? To get to the bottom of this, I'd try substituting your Face[] parameter with a large-enough a byte[] and see if the byte array gets filled with anything (you'll have to change your [DllExport] a bit).
Also, one other thing I used to experience when doing this with char*'s is that I had to pre-allocate the buffer in C#. For example:
would not work. But assuming that returned theString was a max 256 characters, I would do this:
And I'd be in business. I'd recommend trying the byte[] substitution, if that doesn't work, try the pre-allocated byte array. Once you are seeing the byte array actually get changed by your C++ code, then you can figure out how to marshal that thing into your C# struct.