C++ 函数到 C#

Posted

技术标签:

【中文标题】C++ 函数到 C#【英文标题】:C++ function to 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++方法?

【问题讨论】:

可能是respective sizes of the bool 可能的 c++ 名称修改 @MickyDuncan 如果是这样,那么错误会有所不同。该错误会报告找不到该函数。 @DavidHeffernan 是的。谢谢你 【参考方案1】:

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

    C++ 代码使用cdecl,C# 代码使用stdcall。这不匹配。 C++ 代码按值传递HWND。 C# 代码有一个IntPtr 作为out 参数传递。这不匹配。 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 中提问。但是,这里已经提出了这个问题:***.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);
        
    

【讨论】:

以上是关于C++ 函数到 C#的主要内容,如果未能解决你的问题,请参考以下文章

C++ 回调函数到 C#

将二维双数组从 C# 传递到 C++ 函数

如何将委托或函数指针从 C# 传递到 C++ 并使用 InternalCall 调用它

如何使用 p/invoke 终止从 C# 调用的 C++ 函数

从 C++ 传递函数指针以由 C# 调用 - 函数参数包括宽字符字符串 (LPCWSTR)

PInvokeStackImbalance C# 调用非托管 C++ 函数