开发者

Making C++ DLL for C#

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 m开发者_如何学Pythonatch 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.


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


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);
    
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜