472,779 Members | 2,640 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,779 software developers and data experts.

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

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

May 24 '07 #1
6 7564
sm****@hotmail.com wrote:
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.

--
SvenC

May 24 '07 #2
sm****@hotmail.com wrote:
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
May 24 '07 #3

"Carl Daniel [VC++ MVP]" <cp*****************************@mvps.org.nospam >
wrote in message news:eu*************@TK2MSFTNGP06.phx.gbl...
sm****@hotmail.com wrote:
>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.
I believe that .NET makes this very easy, with
Marshal.GetFunctionPointerForDelegate, since the JIT habitually does dynamic
code generation.
>
-cd


May 24 '07 #4
On May 24, 11:08 am, "Ben Voigt" <r...@nospam.nospamwrote:
"Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nos...@mvps.org.nospam >
wrote in messagenews:eu*************@TK2MSFTNGP06.phx.gbl.. .


smm...@hotmail.com wrote:
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.

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.

May 24 '07 #5
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,

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.

May 24 '07 #6
Ben Voigt wrote:
"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
May 25 '07 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: kurtcobain1978 | last post by:
-------------------------------------------------------------------------------- I need to do the exactly same thing in VB.NET. Load a unmanaged C DLL dynamically and then call a function in...
0
by: Lonewolf | last post by:
Hi, I'm not sure if this has been asked before so please pardon me if this is a repeated question. Basically I have some performance critical directshow codes which is implemented in native,...
0
by: draskin | last post by:
Hello, I have the following situation: - Text.exe creates a new AppDomain - Test.exe loads mixed mode assembly in a non-default AppDomain - Test.exe calls connect to a TCP/IP socket server which...
12
by: DaTurk | last post by:
Hi, I have a rather interesting problem. I have a unmanged c++ class which needs to communicate information to managed c++ via callbacks, with a layer of c# on top of the managed c++ ultimatley...
3
by: Builder | last post by:
Hello, I created a DirectShow filter which detects faces from video. Filter exposes interface, which enables to set a callback, which is called when a face is detected. I made an application in...
0
by: DavidT | last post by:
Hello, at first, exuse if the following question is simple to solve, but i normaly coding with C# and now have to use C++/CLI for one project. My Problem is that i have to use a native c++ sdk...
0
by: nabil035 | last post by:
I explain exactly what I want to do: write a callback function in a C++/CLI application this application imports function from a native DLL call this function from the DLL and return the...
0
by: DaTurk | last post by:
Hi, I'm writing an application that has a native c++ layer, and a CLi/C++ layer above it. Above the CLi layer will be C# but that's not relavent to this post. My question has to do with...
1
by: DaTurk | last post by:
Sorry, some how I clicked post before I finished. Hi, I'm writing an application that has a native c++ layer, and a CLi/C++ layer above it. Above the CLi layer will be C# but that's not...
1
by: DaTurk | last post by:
Hi, I'm writing an application that has a native c++ layer, and a CLi/C++ layer above it. Above the CLi layer will be C# but that's not relavent to this post. My question has to do with...
0
by: Rina0 | last post by:
Cybersecurity engineering is a specialized field that focuses on the design, development, and implementation of systems, processes, and technologies that protect against cyber threats and...
0
by: erikbower65 | last post by:
Using CodiumAI's pr-agent is simple and powerful. Follow these steps: 1. Install CodiumAI CLI: Ensure Node.js is installed, then run 'npm install -g codiumai' in the terminal. 2. Connect to...
0
linyimin
by: linyimin | last post by:
Spring Startup Analyzer generates an interactive Spring application startup report that lets you understand what contributes to the application startup time and helps to optimize it. Support for...
0
by: kcodez | last post by:
As a H5 game development enthusiast, I recently wrote a very interesting little game - Toy Claw ((http://claw.kjeek.com/))。Here I will summarize and share the development experience here, and hope it...
0
by: Taofi | last post by:
I try to insert a new record but the error message says the number of query names and destination fields are not the same This are my field names ID, Budgeted, Actual, Status and Differences ...
14
DJRhino1175
by: DJRhino1175 | last post by:
When I run this code I get an error, its Run-time error# 424 Object required...This is my first attempt at doing something like this. I test the entire code and it worked until I added this - If...
0
by: Rina0 | last post by:
I am looking for a Python code to find the longest common subsequence of two strings. I found this blog post that describes the length of longest common subsequence problem and provides a solution in...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
0
by: Mushico | last post by:
How to calculate date of retirement from date of birth

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.