将包含数组的 C 结构编组到 C#

发布于 2024-12-19 04:35:49 字数 1246 浏览 1 评论 0原文

stackoverflow 社区的大力帮助下,我成功调用了本机 DLL 函数。但是,我无法修改 IDintersects 数组的值。无论我在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

云淡风轻 2024-12-26 04:35:49

您必须明确告诉 pinvoke 编组器该数组需要被编回。您可以使用 [In] 和 [Out] 属性来执行此操作。像这样:

    [DllImport("...")]
    public static extern int solve([In, Out] Face[] faces, int len);

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:

    [DllImport("...")]
    public static extern int solve([In, Out] Face[] faces, int len);
若水微香 2024-12-26 04:35:49

这只是一个输出字段?为了深入了解这一点,我尝试用足够大的 byte[] 替换您的 Face[] 参数,并查看字节数组是否填充了任何内容(您必须稍微更改您的 [DllExport] )。

另外,我在使用 char* 执行此操作时遇到的另一件事是我必须在 C# 中预先分配缓冲区。例如:

StringBuilder theString=new StringBuilder();
MyUnmanagedFunction(theString);

不起作用。但假设返回的 theString 最多为 256 个字符,我会这样做:

StringBuilder theString=new StringBuilder(256);
MyUnmanagedFunction(theString);

而且我会做生意。我建议尝试 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:

StringBuilder theString=new StringBuilder();
MyUnmanagedFunction(theString);

would not work. But assuming that returned theString was a max 256 characters, I would do this:

StringBuilder theString=new StringBuilder(256);
MyUnmanagedFunction(theString);

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文