2011-10-05 43 views
3

我做了一个非常简单的DLL是这样的:使C++ DLL的C#

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(); 
    } 
} 

这是工作,直到我曾尝试传递参数。现在,我已经在运行时出现以下错误:“!ConsoleApplication2 ConsoleApplication1.Program ::试试”

到的PInvoke函数 调用具有不平衡 堆栈。这很可能是因为托管的PInvoke签名 与非托管目标签名不匹配。检查呼叫 约定和PInvoke签名的参数是否与目标 非托管签名相匹配。

我不知道问题出在哪里。

+4

让它'INT __stdcall尝试(int v)按'在你的C++代码。 –

回答

5

错误信息你有一个很好的建议:

检查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(); 
    } 
} 
 
+0

谢谢你的帮助。我刚开始学习有关DLL的知识,并在C#中使用它。我只想要一个简单的工作代码。再次谢谢你的解释。 –

2

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

  • 要么让你的原生功能__stdcall,汉斯·建议:

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

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