Making C++ DLL for C#

2019-02-24 22:38发布

I have 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# app:

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 was working until I have tried to pas parameter. Now I have following error at runtime:

A call to PInvoke function 'ConsoleApplication2!ConsoleApplication1.Program::Try' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

I have no idea where is the problem.

标签: c# c++ dll
2条回答
劳资没心,怎么记你
2楼-- · 2019-02-24 23:00

The error message you've got contains a good advice indeed:

Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

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


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

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


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

查看更多
Emotional °昔
3楼-- · 2019-02-24 23:05

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 these two.

  • 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);
    
查看更多
登录 后发表回答