gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 17:12:03 26 4
gpt4 key购买 nike

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

在我看来,我必须返回一个灵活的二维数组,可能在一个结构中。

关于如何做到这一点有什么建议吗?关于如何在 C 中返回它以及如何在 C# 中访问它的两种想法都受到高度赞赏。

最佳答案

结构的链表可以传回,但处理起来会很麻烦,因为您必须编写代码来遍历指针,从中读取和复制数据 native 内存转换为托管内存空间。我会推荐一个简单的结构数组。

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

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

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

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

现在要传回数组,最简单的方法是让您的 native 代码分配数组并将其作为指针传回,同时还有另一个指定元素大小的指针。

您的 C 原型(prototype)可能如下所示:

// 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 声明将是这样的:

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

MarshalAs 属性指定应使用第二个参数中指定的大小来编码(marshal)数组(您可以在 MSDN,"Default Marshaling for Arrays" 上阅读更多相关信息)。

如果您使用这种方法,请注意您必须使用CoTaskMemAlloc分配 native 缓冲区,因为这是 .NET 编码(marshal)拆收器所期望的。否则,您的应用程序将出现内存泄漏和/或其他错误。

这是我在验证我的答案时编译的简单示例的片段:

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

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

关于c# - 使用 PInvoke 将点 (x,y,z) 列表从 C 返回到 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8627592/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com