【发布时间】:2015-03-09 22:08:29
【问题描述】:
我有一个 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。但是,它始终作为无符号字符指针传递。
为了简单起见,我只是尝试让至少一种变体起作用。这是我为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 声明有错误。我尝试了巨大的缓冲区(它可以保存我期望的任何类型的数据),但我的猜测是,我的错误在声明中。
我还尝试在 p/invoke 声明中将缓冲区声明为 byte[](因为示例将其转换为 unsigned char*)和 ulong。我作为参考传递的实际缓冲区相同。错误依旧。
我怎样才能做到这一点?
【问题讨论】:
-
没有完整的代码示例,不可能提供具体的建议。但我要指出,C++
long等价于 C#int。因此,您的 p/invoke 方法声明与非托管代码不匹配(即,为缓冲区大小传递 64 位 int 而非托管代码需要 32 位 int)。仅此一项就可以解释这次崩溃。
标签: c# c++ c pinvoke dllimport