引用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#引用标识符,甚至不确定是否需要手动指针封送。如果你们当中有谁能给我指路,我将永远感激不尽。

引用c# PInvoke中的对象数组

我终于找到了我的问题的解决方案,我把这个贴出来给任何需要澄清的人:

首先,正如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];
}