4

I have a DLL that is written in C++ that includes exported function that has a function pointers to be used as callback function.

// C++ 
DllExport unsigned int DllFunctionPointer( unsigned int i, unsigned int (*TimesThree)( unsigned int number ) ) {
    return TimesThree( i )  ; 
}

I have a CSharp application that I would like to use to invoke the DLL functions.

// C#
public unsafe delegate System.UInt32 CallBack( System.UInt32 number ); 
class Program
{
    [DllImport("SimpleDLL.dll")]
    public static extern System.UInt32 DllFunctionPointer( System.UInt32 i, CallBack cb) ;

    static unsafe void Main(string[] args)
    {
        System.UInt32 j = 3;
        System.UInt32 jRet = DllFunctionPointer(j, CallBack );
        System.Console.WriteLine("j={0}, jRet={1}", j, jRet); 
    }

    static System.UInt32 CallBack( System.UInt32 number ) {
        return number * 3 ; 
    }
}

The problem with the above code is that the application crashes with the following error message.

'CallingACallbackFromADLL.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\XXXX\CallingACallbackFromADLL.exe', Symbols loaded.
Managed Debugging Assistant 'PInvokeStackImbalance' has detected a problem in 'C:\XXXX\CallingACallbackFromADLL.vshost.exe'.
Additional Information: A call to PInvoke function 'CallingACallbackFromADLL!CallingACallbackFromADLL.Program::DllFunction' 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.

The program '[9136] CallingACallbackFromADLL.vshost.exe: Managed (v4.0.30319)' has exited with code 1073741855 (0x4000001f).

I am not sure what to do next.

My question is:

  • What is the correct way to call a C++ DLL function that contains a Callback pointer from a C# application.
slugster
  • 49,403
  • 14
  • 95
  • 145
Steven Smethurst
  • 4,495
  • 15
  • 55
  • 92
  • 1
    Possible doop of http://stackoverflow.com/questions/5235445/pinvoke-c-function-takes-pointer-to-function-as-argument – avishayp Nov 07 '12 at 23:58

1 Answers1

3

This is because by default calling convention of functions in C# is __stdcall but in C/C++ default is __cdecl, so you should change calling convention of your function as follow:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void TimesTree( uint frame );
[DllImport("SimpleDLL.dll")]
public static extern System.UInt32 DllFunctionPointer( uint i,
    [MarshalAs(UnmanagedType.FunctionPtr)] TimesTree callback ) ;

static unsafe void Main(string[] args)
{
    // ...
    System.UInt32 jRet = DllFunctionPointer(j, CallBack );
    // ...
}
BigBoss
  • 6,904
  • 2
  • 23
  • 38
  • 2
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)] This is only needed if you run in x86 (Win32 / WoW64) mode. In 64-bit mode, there is only one calling convention and this attribute is ignored. If you develop on x64 machine, you may easily forget about that special treatment for 32-bit. – linquize Nov 08 '12 at 03:10
  • @linquize The error `unbalanced the stack` can only caused by `underflow/overflow` in stack variables in C++ functions(in `C#` you can't do that) or bad calling convention. So caller certainly is not running code on X64 mode! – BigBoss Nov 08 '12 at 08:29