C++DLL与C#的互操作:公开未知大小的多维数组和内存管理
C++ DLL Interop with C#: Exposing multidimensional arrays of unknown size, and memory-management
我有一个C++库,它做一些核心的金融数学(Quantlib)。我有一个针对它构建的普通C++dll,它向C#前端应用程序公开了一个轻量级接口,允许用户传入各种参数、运行场景等。然后dll返回数据以供显示。
然而,我真的不清楚如何处理dll和C#层之间的接口,尤其是我不知道在哪里处理内存分配/释放,即在C#或dll 中
本质上,我希望我的dll返回一个类或结构,该类或结构包含一个2维值数组(double、char*等)。在我调用dll时,我不知道这个数组的大小,所以我想它必须由dll本身分配。
目前,dll返回了一个looooooong char*,其中包含一个由管道分隔的值列表。这似乎有效,但我觉得它不是一个特别优雅的解决方案。
有什么帮助吗,伙计们?
编辑
非常感谢您的反馈。对不起,我已经好几年没有做任何DLL编程了,所以这个问题有点愚蠢。
我决定简单地将2d数组视为一个在C++侧具有高度/宽度偏移的1d数组,并直接猜测数组的大小。在C#端创建一个2d数组,并以这种方式将其编组到C++似乎效果不错。
这是我的东西。有什么想法吗?
C#:
[DllImport(<dllPath>, CallingConvention = CallingConvention.Cdecl)]
static extern void ChangeArray2d(double[,] arr, int l1, int l2);
//populated with some sample values
double[,] arr = new double[,] { { 1, 2, 3, 4 }, { 5, 6, 7, 8 } };
ChangeArray2d(arr, arr.GetLength(0), arr.GetLength(1));
C++:
__declspec(dllexport) void ChangeArray2d( double* arrayin, int height, int width)
{
for (int n = 0; n<height; n++){
for (int m = 0; m<width; m++){
arrayin[n*width+m] = arrayin[n*width+m] + 100;
}
};
return;
}
通常情况下,分配缓冲区,将其(缓冲区大小为您一次可以处理的最大数据量)传递给C++本机函数,由其填充缓冲区,然后处理数据/释放缓冲区是常见的模式。或者重复使用缓冲区。
如果您的本机函数为您分配了缓冲区,然后您应该释放它——这是一个不同的脆弱契约,也禁止内存重用。例如,如果您需要调用此函数20次,则会有20次不必要的分配。
类似的东西:
private int YourNativeFunctionStub(IntPtr buffer, int bufferSize)
{
int writtenToBufferBytes = bufferSize; // if it wrote less to buffer - it should return correct count of bytes
// here your library fills the buffer with data
return writtenToBufferBytes;
}
private double[] GetArrayFromNative()
{
int bufsize = 1024; // probably you should find it by calling another func from your library?
IntPtr nativeBuffer = Marshal.AllocHGlobal(bufsize);
try
{
int bytesReceivedInBuffer = YourNativeFunctionStub(nativeBuffer, bufsize);
int receivedArrayLength = bytesReceivedInBuffer / sizeof(double);
var managedArray = new double[receivedArrayLength];
Marshal.Copy(nativeBuffer, managedArray, 0, receivedArrayLength);
return managedArray;
}
finally
{
Marshal.FreeHGlobal(nativeBuffer);
}
}
UPD:参见汉斯的评论。
相关文章:
- 如何初始化由unique_ptr管理的数组的元素?
- 坚持将双指针管理的内存复制到二维数组
- 我正在努力处理多维数组输入和输出,我管理输入,但是打印无法按计划工作
- C++ 使用数组初始化时的 STL 向量内存管理
- 使用unique_ptr来管理三维数组
- 将字节数组从c 不受管理的dll传递到c#unity
- Delphi中的动态数组和内存管理
- 当动态创建一个包含另一个动态创建的结构数组的结构数组时,内存管理
- C++内存管理:从函数中的向量创建一个新数组
- 二维数组分配中的内存管理
- 如何有效地管理数组中的堆对象(C++)
- C++ 数组大小以及如何管理大型数组
- 如何管理固定数组中的对象
- 将静态数组转换为 char* 并管理类型转换
- Python数组管理C++等效程序
- 如何在c++中管理数组边界
- 如何管理指向对象的指针数组
- 线程64后数组的内存管理错误
- 内存管理:使用new操作符进行数组和动态分配
- 在c++中有效地管理数组二进制堆句柄