Pinvoke upon return of int, API

2019-09-02 07:20发布

问题:


I am currently running into an issue of calling an Win32 DLL[Native] from a C# windows application.

I have come so far.

C++ source:

extern "C" __declspec(dllexport) int PlaceSound(__in DWORD frequence, __in DWORD duration)
{
    Beep(frequence, duration);
    return 0;
}

C# source:

[DllImport("SampleLib.dll")]
    public extern static int PlaceSound(int Freq, int Dura);

 public form1 { InitializeComponements; PlaceSound(150, 500); }

Upon debugging, I recieve the sound, however, when the library returns its integer value I seem to get a pinvoke.

Pinvoke:
A call to PInvoke function 'SoundTracer!SoundTracer.Form1::PlaceSound' 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.

What am I doing wrong?

回答1:

The default calling convention of the C++ compiler is cdecl, but the default calling convention for p/invoke is stdcall. That mismatch is the reason for the message that you see.

Also, to be 100% correct, DWORD is an unsigned integer and should be matched with uint.

So you need to import it like this:

[DllImport("SampleLib.dll", CallingConvention=CallingConvention.Cdecl)]
public extern static int PlaceSound(uint Freq, uint Dura);


回答2:

Well, PInovke usually defaults to __stdcall/WINAPI/CALLBACK/PASCAL calling convention. Modify C++ source so that the function is WINAPI, or there probably is way to modify your PInvoke declared function to use cdecl calling method. I just always us WINAPI for ease.

extern "C" __declspec(dllexport) int WINAPI PlaceSound(__in DWORD frequence, __in DWORD duration)
{
    Beep(frequence, duration);
    return 0;
}


标签: c# c++ api pinvoke