Before I state the problem, I just want to let the readers know, I am
knew to C++\CLI and interop so please forgive any newbie questions.
I have a huge C library which I want to be able to use in a .NET
application and thus am looking into writing a managed C++ wrapper for
in vs2005. Furthermore, this library has many callback hooks which
need to be implemented by the C++ wrapper.
These callback functions are declared as "extern C __cdecl" which I
am still trying to understand why. However, that is not the main
concern. My main question is , is there any possible way to implement
the callback function to point to a non-static member function rather
than a static function ?
The reason being is that I need to be able to work with multiple
instances of this wrapper, and if the callback functions are limited
to static only, then obviously I would not be able to do this.
I have seen some examples on the web, but those mainly deal with
Windows API's, and don't seem to address this sort of issue.
I would be interested to know if this is possible using delegates, or
whether it is even possible to have the C callback function call a non-
static member function of my C++ wrapper.
Thanks in advance for our help
SvenC - 24 May 2007 07:11 GMT
> I have a huge C library which I want to be able to use in a .NET
> application and thus am looking into writing a managed C++ wrapper for
[quoted text clipped - 3 lines]
> These callback functions are declared as "extern C __cdecl" which I
> am still trying to understand why.
Well, you have to choose a calling convention. extern C controls the name
mangling which mangles less than C++ exports.
> concern. My main question is , is there any possible way to implement
> the callback function to point to a non-static member function rather
> than a static function ?
No, because that defines how the function call is coded when it comes to
machine code. A pointer to a class member function typically needs more
information (the this pointer of the instance e.g.) and more code for being
executed, so you cannot hand this information to a function pointer of the
above type.
> The reason being is that I need to be able to work with multiple
> instances of this wrapper, and if the callback functions are limited
> to static only, then obviously I would not be able to do this.
The only way I see would be that those callbacks would pass you a unique
value which you can control when you initialize a callback. Some sort of
cookie which lets you identify who initiated the callback when you are
called back. But that of course would only work if that library was designed
in that way.
> I have seen some examples on the web, but those mainly deal with
> Windows API's, and don't seem to address this sort of issue.
Sometimes the windows Api uses an LPVOID param which can be seen as such a
cookie. Was it that what you saw?
> I would be interested to know if this is possible using delegates, or
Don't think so.
> whether it is even possible to have the C callback function call a
> non- static member function of my C++ wrapper.
Don't think so either.
--
SvenC
Carl Daniel [VC++ MVP] - 24 May 2007 14:18 GMT
> Before I state the problem, I just want to let the readers know, I am
> knew to C++\CLI and interop so please forgive any newbie questions.
[quoted text clipped - 20 lines]
> whether it is even possible to have the C callback function call a
> non- static member function of my C++ wrapper.
There are basically two approaches to getting into a member function of some
class instance from a simple function pointer callback.
1. The API that uses the callback includes a "context" parameter of
sufficient size to hold a pointer. For example, you might have declarations
something like this:
void RegisterCallback(int (*cbfn)(int p1,int p2,void* context), void*
context);
Here, a hypothetical callback registration function accepts a pointer to a
function and an additional void* argument. When the callback is called, the
context argument of the register function is passed to the context parameter
of the callback function. Many Windows APIs that use callbacks use this
pattern.
In a case like this, you can write a small "trampoline function" that makes
the jump from a simple function to a member function:
class SomeClass(
{
// ...
int Callback(int p1, int p2) { ... }
};
int CallbackTrampoline(int p1, int p2, void* context)
{
return static_cast<SomeClass*>(context)->Callback(p1,p2);
}
2. The API doesn't provide a context object (or "cookie").
In this case, the API was simply not designed to support object-oriented
usage, so your only recourse for getting the callback to call into a member
function involves dynamic code generation. Basically, you have to write
code that generates the above trampoline function at runtime, burning the
address of the object into the function. Such code is subtle and
non-portable, but the technique is used more than one might guess.
-cd
Ben Voigt - 24 May 2007 16:08 GMT
>> Before I state the problem, I just want to let the readers know, I am
>> knew to C++\CLI and interop so please forgive any newbie questions.
[quoted text clipped - 59 lines]
> burning the address of the object into the function. Such code is subtle
> and non-portable, but the technique is used more than one might guess.
I believe that .NET makes this very easy, with
Marshal.GetFunctionPointerForDelegate, since the JIT habitually does dynamic
code generation.
> -cd
rawhahs - 24 May 2007 16:46 GMT
> > smm...@hotmail.com wrote:
> >> Before I state the problem, I just want to let the readers know, I am
[quoted text clipped - 70 lines]
>
> - Show quoted text -
Ben, Carl, Thanks for your replies. Ben is it possible for you to
put up an example of how to do this using delegates ? I have seen
some posts which do claim that this is possible to do.
Carl,
You are correct the API is not changeable and i am not sure if it was
meant for object oriented programming. Therefore I am not able to
modify it at all, and only have the .h to work with.
Thanks to both of you for your help.
Ben Voigt - 24 May 2007 18:36 GMT
> Ben, Carl, Thanks for your replies. Ben is it possible for you to
> put up an example of how to do this using delegates ? I have seen
> some posts which do claim that this is possible to do.
http://msdn2.microsoft.com/en-us/library/ms776420.aspx
> Carl,
>
[quoted text clipped - 3 lines]
>
> Thanks to both of you for your help.
Carl Daniel [VC++ MVP] - 25 May 2007 05:02 GMT
> "Carl Daniel [VC++ MVP]"
>> In this case, the API was simply not designed to support
[quoted text clipped - 8 lines]
> Marshal.GetFunctionPointerForDelegate, since the JIT habitually does
> dynamic code generation.
Yes - I thought there was a handy .NET shortcut for it, but didn't have any
handy .NET references at hand when I was writing. Sure makes it a lot
easier than the all-native solutions turn out to be!
-cd