【问题标题】:Making C++ DLL for C#为 C# 制作 C++ DLL
【发布时间】:2011-10-05 18:49:12
【问题描述】:

我做了一个非常简单的DLL,如下所示:

extern "C"
{
  __declspec(dllexport) int Try(int v)
  {
    return 10 + v;
  }
}

然后我想在我的 C# 应用程序中使用它:

class Program
{
    [DllImport("TestLib.dll")]
    public static extern int Try(int v);

    static void Main(string[] args)
    {
        Console.WriteLine("Wynik: " + Try(20));
        Console.ReadLine();
    }
}

在我尝试传递参数之前它一直有效。现在我在运行时出现以下错误:

调用 PInvoke 函数 'ConsoleApplication2!ConsoleApplication1.Program::Try' 不平衡 堆栈。这可能是因为托管的 PInvoke 签名确实 与非托管目标签名不匹配。检查调用 PInvoke 签名的约定和参数与目标匹配 非托管签名。

我不知道问题出在哪里。

【问题讨论】:

  • 在你的 C++ 代码中使用int __stdcall Try(int v)

标签: c# c++ dll


【解决方案1】:

您收到的错误消息确实包含一个很好的建议:

检查 PInvoke 签名的调用约定和参数是否与目标非托管签名匹配。

您应该在两边指定相同的调用约定(C++ dll 和 C# 程序集)。在 C++ 中,您可以通过在函数声明前加上 __cdecl、__stdcall 等之一来指定它。

extern "C" { __declspec(dllexport) int __stdcall Try(int v) { return 10 + v; } }

在 C# 端,您使用 DllImport 属性指定它,默认的是 CallingConvention.StdCall,它对应于 C++ 中的 __stdcall,因此,看起来您在 C++ 端有一个 __cdecl。要解决此问题,请在 DLL 中使用 __stdcall,如上所示,或在 C# 中使用 CDecl,如下所示:

class Program { [DllImport("TestLib.dll", CallingConvention=CallingConvention.Cdecl)] public static extern int Try(int v); static void Main(string[] args) { Console.WriteLine("Wynik: " + Try(20)); Console.ReadLine(); } }

【讨论】:

  • 感谢您的帮助。我刚刚开始学习 DLL 并在 C# 中使用它。我只想要一个简单的工作代码开始。再次感谢您的精彩解释。
【解决方案2】:

C 和 C++ 中的默认调用约定是__cdecl; .NET P/Invoke 使用的默认调用约定是__stdcall——您需要协调这两者。

  • 按照 Hans 的建议,创建您的原生函数 __stdcall

    __declspec(dllexport) int __stdcall Try(int v)
    
  • 或者让您的托管 P/Invoke 签名使用__cdecl

    [DllImport("TestLib.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern int Try(int v);
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多