Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# GetFunctionPointerForDelegate cdecl instead of stdcall

I'm trying to work with a (C) third party library that has a callback mechanism that lacks any possible way of identifying the calling context. My main project is in C#, and my wrapper is a C++/CLI project to call the C library APIs.

To work around this problem, I'm attempting to use Marshal::GetFUnctionPointerForDelegate. Here is my C# code:

void Init(Handler Callback)
{
    // Create a wrapper lambda in case Callback is a non-static method.
    instance.CreateBuffers((x, y) => Callback(x, y));
}

Then, in the C++/CLI code:

void CreateBuffers(Handler^ Callback)
{
    pinCallback = GCHandle::Alloc(Callback);

    void (*callback)(int, int) = (void (__stdcall *)(int, int))Marshal::GetFunctionPointerForDelegate(Callback).ToPointer(),
    // Use 'callback' in third party library...
}

The problem with all this is that according to http://msdn.microsoft.com/en-us/library/367eeye0.aspx, the function pointer from Marshal::GetFunctionPointerForDelegate is an stdcall function, but my C callback is cdecl. How can I get a cdecl compatible function here?

like image 290
dsharlet Avatar asked Nov 02 '13 08:11

dsharlet


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.

Is C programming hard?

C is more difficult to learn than JavaScript, but it's a valuable skill to have because most programming languages are actually implemented in C. This is because C is a “machine-level” language. So learning it will teach you how a computer works and will actually make learning new languages in the future easier.


1 Answers

I think that the simpest way to achieve this is to declare your delegate type is C# with the UnmanagedFunctionPointer attribute to specify the calling convention.

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate ...

Then make your C++/CLI code receive a plain native C++ function pointer. You can pass an instance of your delegate, and because the delegate has that attribute, the marshaller knows what to do.

This allows you to skip the GetFunctionPointerForDelegate step. In fact it would allow you to skip right over the C++/CLI layer, but I expect that you don't want to do that.

Make sure that your managed code retains a reference to the delegate for as long as the unmanaged code can see the function pointer. If you don't do so then the garbage collector may pull the rug from under you since it cannot see the reference held by the unmanaged code.

This topic has been covered here before, of course. Hans Passant has a detailed answer here that is worth reading: Correct way to call a C DLL method from C#

like image 163
David Heffernan Avatar answered Sep 28 '22 08:09

David Heffernan