简体   繁体   English

使用PInvoke返回从C到C#的点(x,y,z)列表

[英]Return list of points (x,y,z) from C to C# using PInvoke

I need to return a list of points i have from a C dll to a C# application using PInvoke. 我需要使用PInvoke将我从C dll中获得的点列表返回给C#应用程序。 These are points in 3 dimensions [x,y,z]. 这些是3维[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. 在C i中处理这个结构的链表。 But I don't see how i can pass this on to C#. 但我不知道如何将其传递给C#。

The way I see it, I have to return a flexible two dimensional array, probably in a struct. 我看到它的方式,我必须返回一个灵活的二维数组,可能在一个结构中。

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. 关于如何在C中返回它以及如何在C#中访问它的想法都受到高度赞赏。

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. 我会推荐一个简单的结构数组。

If you have a C struct like the following (assuming 32-bit ints)... 如果您有一个如下所示的C结构(假设32位整数)...

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

... then you'd represent it nearly the same way in C#: ...那么你在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. 现在要传回一个数组,最简单的方法是让你的本机代码分配数组并将其作为指针传回,同时另一个指针指定元素的大小。

Your C prototype might look like this: 您的C原型可能如下所示:

// 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);

The P/Invoke declaration would then be this: P / Invoke声明将是这样的:

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

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" ). MarshalAs属性指定应使用第二个参数中指定的大小封送数组(您可以在MSDN上阅读有关此内容的更多信息, “默认的阵列编组 )。

If you use this approach, note that you must use CoTaskMemAlloc to allocate the native buffer as this is what the .NET marshaler expects. 如果使用此方法,请注意必须使用CoTaskMemAlloc来分配本机缓冲区,因为这是.NET编组程序所期望的。 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;
}

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的静态类中):

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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM