使用PInvoke将点(x,y,z)从C返回到C#的列表 [英] Return list of points (x,y,z) from C to C# using PInvoke

查看:103
本文介绍了使用PInvoke将点(x,y,z)从C返回到C#的列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用PInvoke将我从C dll返回的点列表返回到C#应用程序.这些是3维[x,y,z]中的点.点数因其是哪种模型而异.在C中,我处理此结构的链接列表.但是我不知道如何将其传递给C#.

I need to return a list of points i have from a C dll to a C# application using PInvoke. These are points in 3 dimensions [x,y,z]. The number of points varies by what kind of model it is. In C i handle this a linked list of structs. But I don't see how i can pass this on to C#.

我所看到的方式,我必须返回一个灵活的二维数组,可能是在结构中.

The way I see it, I have to return a flexible two dimensional array, probably in a struct.

关于如何做到这一点的任何建议?关于如何在C中返回它以及如何在C#中访问它的想法都受到高度赞赏.

Any suggestions to how this can be done? Both ideas on how to return it in C and how to access it in C# are highly appreciated.

推荐答案

结构的链接列表可以传递回去,但这很麻烦,因为您必须编写代码以遍历指针,从本地内存读取数据并将其复制到托管内存空间.我会推荐一个简单的结构数组.

A linked list of structs could be passed back, but it would be quite a hassle to deal with, as you would have to write code to loop through the pointers, reading and copying the data from native memory into managed memory space. I would recommend a simple array of structs instead.

如果您具有如下所示的C结构(假定为32位整数)...

If you have a C struct like the following (assuming 32-bit ints)...

struct Point
{
    int x;
    int y;
    int z;
}

...那么您将在C#中以几乎相同的方式表示它:

... then you'd represent it nearly the same way in C#:

[StructLayout(LayoutKind.Sequential]
struct Point
{
    public int x;
    public int y;
    public int z;
}

现在要传递一个数组,最简单的方法是让您的本机代码分配该数组并将其作为一个指针与另一个在元素中指定大小的指针一起传递回去.

Now to pass an array back, it would be easiest to have your native code allocate the array and pass it back as a pointer, along with another pointer specifying the size in elements.

您的C原型可能看起来像这样:

Your C prototype might look like this:

// Return value would represent an error code
// (in case something goes wrong or the caller
// passes some invalid pointer, e.g. a NULL).
// Caller must pass in a valid pointer-to-pointer to
// capture the array and a pointer to capture the size
// in elements.
int GetPoints(Point ** array, int * arraySizeInElements);

P/Invoke声明将是这样:

The P/Invoke declaration would then be this:

[DllImport("YourLib.dll")]
static extern int GetPoints(
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out Point[] array,
    out int arraySizeInElements);

MarshalAs属性指定应使用第二个参数中指定的大小对数组进行封送处理(您可以在MSDN ).

The MarshalAs attribute specifies that the array should be marshaled using the size specified in the second parameter (you can read more about this at MSDN, "Default Marshaling for Arrays").

如果使用这种方法,请注意,您必须使用

If you use this approach, note that you must use CoTaskMemAlloc to allocate the native buffer as this is what the .NET marshaler expects. Otherwise, you will get memory leaks and/or other errors in your application.

这是我在验证答案时编写的简单示例的摘录:

Here is a snippet from the simple example I compiled while verifying my answer:

struct Point
{
    int x;
    int y;
    int z;
};

extern "C"
int GetPoints(Point ** array, int * arraySizeInElements)
{
    // Always return 3 items for this simple example.
    *arraySizeInElements = 3;

    // MUST use CoTaskMemAlloc to allocate (from ole32.dll)
    int bytesToAlloc = sizeof(Point) * (*arraySizeInElements);
    Point * a = static_cast<Point *>(CoTaskMemAlloc(bytesToAlloc));
    *array = a;

    Point p1 = { 1, 2, 3 };
    a[0] = p1;

    Point p2 = { 4, 5, 6 };
    a[1] = p2;

    Point p3 = { 7, 8, 9 };
    a[2] = p3;

    return 0;
}

然后,托管调用方可以非常简单地处理数据(在此示例中,我将所有互操作代码放在了名为NativeMethods的静态类中):

The managed caller can then deal with the data very simply (in this example, I put all the interop code inside a static class called NativeMethods):

NativeMethods.Point[] points;
int size;
int result = NativeMethods.GetPoints(out points, out size);
if (result == 0)
{
    Console.WriteLine("{0} points returned.", size);
    foreach (NativeMethods.Point point in points)
    {
        Console.WriteLine("({0}, {1}, {2})", point.x, point.y, point.z);
    }
}

这篇关于使用PInvoke将点(x,y,z)从C返回到C#的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆