Creating a C ++ DLL for C #

I made a very simple DLL like this:

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

Then I want to use it in my C # application:

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

It worked until I tried to use the pas parameter. Now at runtime there is an error:

The PInvoke function call "ConsoleApplication2! ConsoleApplication1.Program :: Try" has an unbalanced stack. This is likely due to the fact that the PInvoke managed signature does not match the unmanaged target signature. Verify that the invocation agreement and PInvoke signature settings match the target unmanaged signature.

I do not know where the problem is.

+3
source share
2 answers

The error message you have contains good advice:

Verify that the calling agreement and PInvoke signature settings match the target unmanaged signature.

You should have the same calling convention indicated on both sides (C ++ dll and C # build). In C ++, you can specify it by adding a function declaration with one of __cdecl, __stdcall, etc.

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

On the C # side, you specify it with the DllImport attribute, the default is CallingConvention.StdCall, which corresponds to __stdcall in C ++, so it looks like you have __cdecl on the C ++ side. To fix the problem, use __stdcall in your DLL, as shown above, or use CDecl in C #, for example:

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

The default calling convention in C and C ++ is __cdecl ; the default calling convention used by .NET P / Invoke is __stdcall - you need to reconcile the two.

  • Or make your own __stdcall function as suggested by Hans:

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

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

All Articles