Callback function from native C to C++\CLI using non-static member or delegates

S

smmk25

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
 
S

SvenC

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.

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.
 
C

Carl Daniel [VC++ MVP]

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.

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
 
B

Ben Voigt

Carl Daniel said:
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.

I believe that .NET makes this very easy, with
Marshal.GetFunctionPointerForDelegate, since the JIT habitually does dynamic
code generation.
 
R

rawhahs

"Carl Daniel [VC++ MVP]" <[email protected]>
wrote in message



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.

I believe that .NET makes this very easy, with
Marshal.GetFunctionPointerForDelegate, since the JIT habitually does dynamic
code generation.




-cd- Hide quoted text -

- Show quoted text -- Hide quoted text -

- 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.
 
C

Carl Daniel [VC++ MVP]

Ben said:
"Carl Daniel [VC++ MVP]"
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.

I believe that .NET makes this very easy, with
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top