【问题标题】:How to set or get parameter to DLL library in C#?如何在 C# 中设置或获取 DLL 库的参数?
【发布时间】: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。

我尝试过:

  1. Marshal.Copy(...) 或 Marshal.ReadByte(...) 返回以下异常: mscorlib.dll 中出现“System.AccessViolationException”类型的未处理异常附加信息:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

  2. 尝试在 x86 Windows 7 上运行:DLL 结果相同(错误结果)。

  3. 尝试将 IntPtr 更改为 byte[] 我得到了与 Marshal.Copy() 中相同的异常

  4. 试图用 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


【解决方案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);

【讨论】:

  • 第一个:我完全改变它,就像你一样,但我有相同的结果。对于 ref ushort stat 结果是 0x003 正确的必须是 0x000 和 0x004 正确的胸围是 0x001 :-( 我正在尝试的第二个。
  • 在第二个示例中,当我使用 Cdecl: CallingConvention.Cdecl 时,出现以下异常:托管调试助手“PInvokeStackImbalance”在“C:\Users....”中检测到问题。其他信息:调用 PInvoke 函数
  • 您可以删除CallingConvention 并重试。如果你知道字符集就更好了,你可以直接指定它
  • 我删除了 Cdecl,但结果是:mscorlib.dll 中发生了“System.AccessViolationException”类型的未处理异常附加信息:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。
  • 这不是 cdecl。别再猜了。
猜你喜欢
  • 1970-01-01
  • 2012-01-26
  • 1970-01-01
  • 2015-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-20
相关资源
最近更新 更多