引用c# PInvoke中的对象数组
本文关键字:对象 数组 PInvoke 引用 | 更新日期: 2023-09-27 17:53:40
我正在构建一个使用c# GUI和本地c++逻辑dll的光谱应用程序。我试图使dll填充一个简单的c++结构体数组,由c#方面的引用传递。然而,当我试图打印[应该被填充]数组元素,我得到系统。NullReferenceExceptions和数组元素在内存中被标记为null。
下面是c++结构定义和方法实现:
typedef struct intensitytype {
unsigned short usEchelleOrder; // echelle order
unsigned short usPixel; // horizontal camera pixel index (unbinned !!)
double dIntensity; // intensity
double dWaveLen; // wave length [nm]
} intensitytype;
void CameraControl::getResults(intensitytype* graphData)
{
graphData = _spectroData; // _spectroData is a pointer to a dynamic intensitytype array.
}
下面是c#类定义和签名
[StructLayout(LayoutKind.Sequential)]
public class intensitytype
{
public ushort usEchelleOrder = 0; // echelle order
public ushort usPixel = 0; // horizontal camera pixel index (unbinned !!)
public double dIntensity = 0; // intensity
public double dWaveLen = 0; // wave length [nm]
}
[DllImport(@"Elemission.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void getResults(bool freeData, out intensitytype[] graphData);
我不确定在这个实例中需要什么类型的c#引用标识符,甚至不确定是否需要手动指针封送。如果你们当中有谁能给我指路,我将永远感激不尽。
我终于找到了我的问题的解决方案,我把这个贴出来给任何需要澄清的人:
首先,正如David指出的那样,简单地将引用的实参当作指针并为其分配数组地址是行不通的。您必须将整个数组内容复制到引用的数组中。容易固定。
第二个错误在c#方法签名中;这里需要的描述是"[Out]",加上括号,而不是简单的"Out"(再次感谢David)。
所以,最终的结果是:
结构不会改变,但是c#中的函数签名会改变:
[DllImport(@"Elemission.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void getResults([Out] intensityType[] graphData);
,这里是函数调用的一个片段:
int arraySize;
DllMethods.executeAcquisition(out arraySize); // arraySize is the Struct array length
intensityType[] resultData = new intensityType[arraySize];
DllMethods.getResults(resultData);
同时在c++中,c#调用由包装器接收并传递给成员函数…
__declspec(dllexport) void getResults(intensitytype* graphData)
{
MainControl::getInstance()->getCamera()->getResults(graphData);
}
…瞧,struct数组被填满了。
void CameraControl::getResults(intensitytype* graphData)
{
for (int i = 0; i < _spectroDataLength; i++)
graphData[i] = _spectroData[i];
}