使用C ++创建C# DLL

3

我制作了一个非常简单的 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签名的调用约定和参数是否与目标非托管签名相匹配。

我不知道问题出在哪里。


4
请将您的C++代码中的函数改为 int __stdcall Try(int v) - Hans Passant
2个回答

5
你收到的错误信息实际上包含了一个很好的建议:
检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。
你应该在两端指定相同的调用约定(C++ dll和C#程序集)。在C++中,您可以通过在函数声明前加上__cdecl、__stdcall等来指定它。
在C#中,您可以使用DllImport属性指定它,默认值是CallingConvention.StdCall,对应于C++中的__stdcall,因此看起来您在C++中使用的是__cdecl。要解决这个问题,您可以像上面那样在DLL中使用__stdcall,或者在C#中使用CDecl,如下所示:

非常感谢您的帮助。我刚开始学习关于DLL和在C#中使用它。我只想要一个简单可用的代码来入门。再次感谢您详细的解释。 - Michał Jankowski

3

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

  • Either make your native function __stdcall, as Hans suggested:

    __declspec(dllexport) int __stdcall Try(int v)
    
  • Or make your managed P/Invoke signature use __cdecl:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接