C# marhsal 函数返回指向结构数组的指针
C# marhsal function returning pointer to array of structs
有一个 C++ 库包含
- 结构
SimpleStruct
- 函数
GetSimpleStructs
返回指向该结构数组的指针
像这样:
typedef struct {
int value1;
int value2;
int value3;
} SimpleStruct;
extern SimpleStruct *GetSimpleStructs(int *count);
我在 C# .Net Core 项目中有这个实现:
[StructLayout(LayoutKind.Sequential)]
struct SimpleStruct
{
int value1;
int value2;
int value3;
}
[DllImport(LibName)]
public static extern IntPtr GetSimpleStructs(out int count);
以及将 IntPtr
转换为 SimpleStruct[]
的函数:
SimpleStruct[] GetSimpleStructs()
{
var ptrToArray = GetSimpleStructs(out var count);
var arrayOfPtrs = new IntPtr[count];
var resultArray = new SimpleStruct[count];
Marshal.Copy(ptrToArray, arrayOfPtrs, 0, count);
for (var i = 0; i < count; i++)
resultArray[i] = Marshal.PtrToStructure<SimpleStruct>(arrayOfPtrs[i]); // HERE
return resultArray;
}
在 // HERE
行之前一切正常。在第一次迭代中,程序以退出代码 139 结束,没有任何异常。
那我做错了什么?
此外,我无法在 DllImport
的项目中引用带有结构的项目
如果您的非托管方法 return 是一个指向结构块的指针,则不需要 IntPtr[]
步骤 - 只有一个指针 (如果您正在 returning SimpleStruct **
,那将很有用)。
相反,您首先需要使用明确的布局属性确保布局完全正确(包括大小),然后:只需通过指针:
unsafe
{
SomeStruct* ptr = (SomeStruct*)ptrToArray.ToPointer();
var resultArray = new SimpleStruct[count];
for (int i = 0 ; i < resultArray.Length ; i++)
resultArray[i] = *ptr[i];
}
如果您乐于使用 span,这会更容易。复制步骤就是:
var resultArray = new Span<SomeStruct>(
ptrToArray.ToPointer(), count).ToArray();
事实上,您可以 return Span<SomeStruct>
或 Memory<SomeStruct>
(后者需要 an extra step, but is possible),以允许安全 C# 代码直接从非托管内存位置访问数据,而无需将其复制到托管内存或分配数组!
有一个 C++ 库包含
- 结构
SimpleStruct
- 函数
GetSimpleStructs
返回指向该结构数组的指针
像这样:
typedef struct {
int value1;
int value2;
int value3;
} SimpleStruct;
extern SimpleStruct *GetSimpleStructs(int *count);
我在 C# .Net Core 项目中有这个实现:
[StructLayout(LayoutKind.Sequential)]
struct SimpleStruct
{
int value1;
int value2;
int value3;
}
[DllImport(LibName)]
public static extern IntPtr GetSimpleStructs(out int count);
以及将 IntPtr
转换为 SimpleStruct[]
的函数:
SimpleStruct[] GetSimpleStructs()
{
var ptrToArray = GetSimpleStructs(out var count);
var arrayOfPtrs = new IntPtr[count];
var resultArray = new SimpleStruct[count];
Marshal.Copy(ptrToArray, arrayOfPtrs, 0, count);
for (var i = 0; i < count; i++)
resultArray[i] = Marshal.PtrToStructure<SimpleStruct>(arrayOfPtrs[i]); // HERE
return resultArray;
}
在 // HERE
行之前一切正常。在第一次迭代中,程序以退出代码 139 结束,没有任何异常。
那我做错了什么?
此外,我无法在 DllImport
如果您的非托管方法 return 是一个指向结构块的指针,则不需要 IntPtr[]
步骤 - 只有一个指针 (如果您正在 returning SimpleStruct **
,那将很有用)。
相反,您首先需要使用明确的布局属性确保布局完全正确(包括大小),然后:只需通过指针:
unsafe
{
SomeStruct* ptr = (SomeStruct*)ptrToArray.ToPointer();
var resultArray = new SimpleStruct[count];
for (int i = 0 ; i < resultArray.Length ; i++)
resultArray[i] = *ptr[i];
}
如果您乐于使用 span,这会更容易。复制步骤就是:
var resultArray = new Span<SomeStruct>(
ptrToArray.ToPointer(), count).ToArray();
事实上,您可以 return Span<SomeStruct>
或 Memory<SomeStruct>
(后者需要 an extra step, but is possible),以允许安全 C# 代码直接从非托管内存位置访问数据,而无需将其复制到托管内存或分配数组!