【发布时间】:2017-03-29 18:38:49
【问题描述】:
我有 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 换掉 // 没有帮助
示例 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.
【问题讨论】:
-
您的 pinvoke 完全错误。在继续之前,您需要更好地了解。
-
@DavidHeffernan THX,对不起,我编辑了第一个示例,但结果与以前相同。请检查一下。谢谢你的任何想法。
-
还是错了。这是公然错误的。你有没有想过这个问题?只需阅读您写的问题。并思考。
-
@DavidHeffernan 如果它明显错误,请帮助我了解究竟是什么不好,并给我一个具体的例子来理解它。谢谢。
-
其实我读错了。对不起。真丢人。
uint是正确的。显然,这并不重要。当然,您应该检查预期的返回值。因此,鉴于我们拥有的信息,Arnaud 的 p/invoke 是完美的。你为什么不用它?
标签: c# c++ variables winapi dllimport