C#编组一个ushort / ulong数组

时间:2015-01-12 07:10:36

标签: c# c++ c pinvoke dllimport

我有一个C-DLL +头文件,并尝试从C#调用一个函数。我还有一些如何使用该函数的示例C ++代码。这是函数定义:

int GetData(unsigned char* buffer, long bufferSize);

更有趣的部分是示例代码以及如何调用函数:

if(dataSize == 16)
{
  unsigned short* usData = new unsigned short[m_numX * m_numY * 3 / 2];
  GetData( (unsigned char*)usData, m_numX * m_numY * sizeof(unsigned short)  );
} 
else if (dataSize == 32) 
{
  unsigned long* ulData = new unsigned long[m_numX * m_numY];
  GetData( (unsigned char*)ulData, m_numX * m_numY * sizeof(unsigned long)  );
}

因此,根据dataSize变量,实际数据数组可以是ushort或ulong。但是,它始终作为unsigned char指针传递。 为了简单起见,我试图让至少一个变体起作用。这是我为dataSize = 16

尝试的代码
[DllImport("External.dll", EntryPoint = "GetData", CharSet = CharSet.Unicode, CallingConvention =      CallingConvention.Cdecl)]
public static extern int GetData(ref ushort[] pBuffer, long lBufferSize);

long bufferSize1 = numX * numY * 3 / 2;
long bufferSize2 = numX * numY * sizeof(ushort);
ushort[] data = new ushort[bufferSize1];

GetData(ref data, bufferSize2)

如果我运行上面的代码,应用程序退出时会出现“访问冲突”异常。这通常意味着,不安全的代码试图写入缓冲区限制或p / invoke声明有错误。我尝试了很大的缓冲区(可以容纳我期望的任何数据),但我的猜测是,我的错误在声明中。

我还尝试将缓冲区声明为byte [](因为该示例将其转换为unsigned char *)并在p / invoke声明中声明ulong。对于作为参考传递的实际缓冲区相同。错误保持不变。

我该如何使这项工作?

1 个答案:

答案 0 :(得分:2)

有几个错误:

  1. 不得将数组作为ref传递。这是因为ref ushort[]匹配unsigned short**
  2. C ++ long与Windows上的C#long不匹配。前者是32位,后者是64位。
  3. 您需要像这样导入:

    [DllImport("External.dll", CallingConvention =      CallingConvention.Cdecl)]
    public static extern int GetData(
        [Out] ushort[] pBuffer, 
        int lBufferSize
    );
    

    为方便起见,对32位数据变量使用重载是完全合理的:

    [DllImport("External.dll", CallingConvention =      CallingConvention.Cdecl)]
    public static extern int GetData(
        [Out] uint[] pBuffer, 
        int lBufferSize
    );
    

    同样,如果需要,byte数组的重载也是有效的。