gpt4 book ai didi

c# - 将 C++ float 组成员直接编码到 c# 而无需复制

转载 作者:搜寻专家 更新时间:2023-10-31 02:05:09 25 4
gpt4 key购买 nike

我有一个矩阵类,其中包含一个固定大小的 float 组,我想在 C# 包装器类中直接公开它:

class Matrix
{
public:
float data[16];
...
};

通常,在 C# 中包装此结构时,我会将包装类型定义为 POD 结构,该结构将利用 [StructLayout(LayoutKind.Sequential)] 并允许我直接将类编码到和来自 C++/C#。但是,c++ 类公开了其他类型(通过成员或函数),这些类型无法以这种方式编码,因此我不得不使用 PIMPL 机制,其中我的 C# 类包含指向底层 C++ 结构的不透明指针 (IntPtr)。但是,我仍然想直接将c++ 结构的底层data 成员暴露给C# 对象。所谓直接,是指对 C# 中 data 元素的修改将直接反射(reflect)在底层 C++ 结构中(即 C# 成员不能是 C++ 成员的拷贝)。我的想法是像这样在 C# 中公开 data 成员:

public class Matrix
{
protected HandleRef cptr; // opaque reference to equivalent C++ instance
public float [] data
{
get
{
return Get_data(cptr);
}
}

[DllImport(MY_CPP_DLL, EntryPoint = "CSharp_Get_data", CharSet = CHARSET)]
[return: MarshalAs(UnmanagedType.LPArray, SizeConst = 16, ArraySubType = UnmanagedType.R4)]
private static extern float [] Get_Data(HandleRef in_object);
};

我的 C++ dll 包含函数 CSharp_Get_data,如下所示:

DLLEXPORT float * STDCALL CSharp_Get_data(Matrix *obj)
{
return obj->data;
}

这在 C++ 和 C# 中都编译得很好,但是当我尝试在 C# 中做这样的事情时:

Matrix asdf = new Matrix();
asdf.data[0] = 2.0f;

我收到一个 System.Runtime.InteropServices.MarshalDirectiveException,它指出 附加信息:无法编码(marshal)“返回值”:无效的托管/非托管类型组合。

有没有一种方法我可以使用这种方法而不遇到这个错误?我知道这是一个非常奇怪的用例,但我觉得这种方法似乎没有违反 MS 在此处描述的任何编码标准:https://learn.microsoft.com/en-us/dotnet/framework/interop/default-marshaling-for-arrays .

感谢您的帮助。

最佳答案

你无法获得 float[]除非.NET 分配内存。 StructLayout(Sequential) 也是如此, 也是——固定大小的缓冲区,例如 float[16]float[] 不兼容.

但是,如果您更想要方便和高效,您可以做什么 float[] , 是使用新的零拷贝缓冲类型。你可以构造一个 System.Span<float>从指向第一个元素的指针加上元素的数量,然后下标该跨度将使您可以直接访问内存。需要进行一些重构,但由于 Span<T>一旦重写代码以使用 Span,就可以同样很好地访问 .NET 数组,它可以存在于两个世界中(C# 和 C++ 分配的数据)。

关于c# - 将 C++ float 组成员直接编码到 c# 而无需复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52414217/

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