C# 封送一个 ushort/ulong 数组
C# Marshaling an ushort/ulong array
我有一个 C-DLL + 头文件并尝试 p/invoke 来自 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)
如果我 运行 以上代码,应用程序将退出并出现 'Access Violation' 异常。这通常意味着,不安全代码试图写入超过缓冲区限制或 p/invoke 声明有错误。我尝试了巨大的缓冲区(它可以容纳我期望的任何类型的数据)但我的猜测是,我的错误在声明中。
我还尝试在 p/invoke 声明中将缓冲区声明为 byte[](因为示例将其转换为 unsigned char*)和 ulong。对于我作为参考传递的实际缓冲区也是如此。错误保持不变。
我怎样才能完成这项工作?
几个错误:
- 数组不得作为
ref
传递。那是因为 ref ushort[]
匹配 unsigned short**
。
- C++
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
数组的重载也是有效的。
我有一个 C-DLL + 头文件并尝试 p/invoke 来自 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)
如果我 运行 以上代码,应用程序将退出并出现 'Access Violation' 异常。这通常意味着,不安全代码试图写入超过缓冲区限制或 p/invoke 声明有错误。我尝试了巨大的缓冲区(它可以容纳我期望的任何类型的数据)但我的猜测是,我的错误在声明中。
我还尝试在 p/invoke 声明中将缓冲区声明为 byte[](因为示例将其转换为 unsigned char*)和 ulong。对于我作为参考传递的实际缓冲区也是如此。错误保持不变。
我怎样才能完成这项工作?
几个错误:
- 数组不得作为
ref
传递。那是因为ref ushort[]
匹配unsigned short**
。 - C++
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
数组的重载也是有效的。