2011-10-05 64 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);