我有一个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。但是,它始终作为无符号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 [](因为该示例将其强制转换为未签名的char *)和ulong在p / invoke声明中。与我作为引用传递的实际缓冲区相同。错误保持不变。
我该如何工作?
最佳答案
几个错误:
ref
传递。那是因为ref ushort[]
与unsigned short**
相匹配。 long
与Windows上的C#long
不匹配。前者是32位,后者是64位。 您需要这样导入:
[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
数组的重载也将有效。