在 C# PInvoke 中引用对象数组

Referencing an object array in C# PInvoke

我正在构建一个使用 C# GUI 和本机 C++ 逻辑 dll 的光谱测量应用程序。我正在尝试使 dll 填充从 C# 端通过引用传递的简单 C++ 结构数组。但是,当我尝试打印 [supposed to be filled] 数组元素时,我得到 System.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# class 定义和签名

[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);
}

...你瞧,结构数组已填充。

void CameraControl::getResults(intensitytype* graphData)
{
    for (int i = 0; i < _spectroDataLength; i++)
        graphData[i] = _spectroData[i];
}