【问题标题】:C++ function to C#C++ 函数到 C#
【发布时间】:2015-02-03 05:27:43
【问题描述】:

我对 C++ 编程完全陌生。我需要从 C# 调用 C++ 函数。

C++ 函数是:

BOOL Usb_Init(HWND hwnd);

我试过了:

[DllImport("UsbComm.dll",  SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool Usb_Init( out IntPtr hwnd);

我收到错误消息:

PInvoke 签名与非托管目标签名不匹配。

如何调用上述C++方法?

【问题讨论】:

  • 可能的 c++ 名称修改
  • @MickyDuncan 如果是这样,那么错误会有所不同。该错误会报告找不到该函数。
  • @DavidHeffernan 是的。谢谢你

标签: c# c++ pinvoke dllimport


【解决方案1】:

我在问题的代码中看到以下错误:

  1. C++ 代码使用cdecl,C# 代码使用stdcall。这不匹配。
  2. C++ 代码按值传递HWND。 C# 代码有一个IntPtr 作为out 参数传递。这不匹配。
  3. DllImport 属性有多个虚假参数。

正确的 C# 声明是:

[DllImport("UsbComm.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool Usb_Init(IntPtr hwnd);

您可以将ExactSpelling 设置为true,但我认为没有令人信服的理由这样做。如果您愿意,请随时添加。指定CharSet 没有意义,因为不涉及文本。而SetLastError = true 可能是个错误。在我看来,非托管函数调用SetLastError 的可能性不大。我的期望是您在尝试消除错误时添加了SetLastError = true

【讨论】:

    【解决方案2】:

    BOOL<windef.h> 中定义为int

    您需要在 C# 的导出声明中使用 int。提醒:值为0等于false;其他的都是true

    public static extern int Usb_Init(out IntPtr hwnd);
    

    而且,您的调用约定也可能是错误的。尝试CallingConvention的每个枚举

    EDIT:工作签名是

    [DllImport("UsbComm.dll", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
    public static extern int Usb_Init(out IntPtr hwnd);
    

    【讨论】:

    • 我试过 DllImport("UsbComm.dll")] public static extern int Usb_Init(out IntPtr hwnd);也称为方法 IntPtr hwnd = new IntPtr(0); var res = Usb_Init(out hwnd);出现签名不匹配错误
    • 谢谢...你拯救了我的一天
    • [DllImport("UsbComm.dll", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern int Usb_Init(out IntPtr hwnd);
    • 您已接受此答案,但它不正确。 hwnd 参数传递不正确。并且没有必要将返回类型设为int。您可以在 C# 中使用 bool,它被编组为 Windows BOOL 类型。
    • 这是一个新问题。而且相当棘手。您可能需要包含更多信息。您不能在 cmets 中提问。但是,这里已经提出了这个问题:stackoverflow.com/questions/28293025/… 我确实认为您需要退后一步,阅读 SO 站点的帮助内容。如果您对如何提出好的问题有更清楚的了解,您将从该网站中获得更多收获。
    【解决方案3】:

    C++ 代码:确保 Usb_Init 的定义应如下所示:

        extern "C" __declspec(dllexport) BOOL __stdcall  Usb_Init(HWND hwnd)
        {
           return TRUE;
        }
    

    C# 代码:

    using System;
    using System.Runtime.InteropServices;
    
    namespace Win32DllClient
    {
    
        class Program
        {
            [DllImport("UsbComm.dll", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
            public static extern bool Usb_Init(out IntPtr hwnd);
            static void Main(string[] args)
            {
                   IntPtr hwnd = new IntPtr(0);
                   var ret = Usb_Init(out hwnd);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-20
      • 2013-08-26
      • 2010-12-15
      • 2021-02-04
      • 2010-10-07
      相关资源
      最近更新 更多