我有C ++库(32位),我想在C#中加载和使用它。 DLL正在工作(打开连接,关闭连接和其他没有参数的方法)。问题是具有参数的C ++库的所有方法的意外结果。例如:
C ++库方法规范:
unsigned int WINAPI acqStatus (WORD& stat, WORD& err);
unsigned int WINAPI getStatus (double& time, TCHAR* data);
C#源代码(外部方法):
[DllImport("DllName.dll")]
public static extern uint acqStatus(ref ushort stat, ref uint err);
[DllImport("DllName.dll")]
public static extern uint getStatus(ref double time, ref StringBuilder data);
C#第一个方法示例(返回错误值,或者我犯了错误,将IntPtr转换为整数):
ushort stat = 0;
uint err = 0;
TCPInterface.acqStatus(ref stat, ref err);
// Result of stat is: 0x0003 or 0x0004
// bad value 3 (expected is 0), bad value 4 (expected is 1)
与另一种方法相同的情况,返回TCHAR *。结果是字符串(字节数组)。我不知道,我是如何从数据变量中获取字符串的。
double time;
StringBuilder data = new StringBuilder();
getStatus(out time, out data);
// Exception:
An unhandled exception of type 'System.AccessViolationException' occurred in mscorlib.dll
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
我正在使用64位Windows 7和Visual Studio 2015.我将我的C#项目设置为x86。
我试图:
Marshal.Copy(...)或Marshal.ReadByte(...)返回以下异常: mscorlib.dll中发生未处理的“System.AccessViolationException”类型异常附加信息:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。
试图在x86 Windows 7上运行:DLL结果相同(结果不好)。
尝试将IntPtr更改为byte []我得到了同样的异常,例如Marshal.Copy()
尝试更改为ref // not help
示例1已更新:
[DllImport("DllName.dll")]
public static unsafe extern int acqStatus(ref ushort* stat, ref uint* err);
// Elsewhere in source code in unsafe method
ushort* stat = 0;
uint* err = 0;
TCPInterface.acqStatus(ref stat, ref err);
// I have following exception:
An unhandled exception of type 'System.AccessViolationException' occurred in WindowsFormsApplication1.exe
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
答案 0 :(得分:1)
那是因为ToInt32()
和ToString()
无法按预期工作。这些方法返回指针的内存地址,而不是检索到的值。
对于第一个签名,请将其更改为:
[DllImport("DllName.dll")]
// WORD C++ is equivalent to ushort in C#
public static extern uint acqStatus(ref ushort stat, ref ushort err);
对于第二个,如果没有确切的实现,它会更复杂,但是一个好的尝试将是:
[DllImport("DllName.dll", CharSet = CharSet.Auto)]
public static extern uint getStatus(ref double time, StringBuilder data);