I'm using a C API (it's actually Spidermonkey's jsapi) with which I
can register callback functions:
void registerCallback(const char * name, CStyleFunctionPtr callback);
I'm trying to wrap and abstract away this API from my users by
offering a pure C++ interface, in which users could implement callback
via functions objects, or something similar. e.g.:
struct FooCallback : public CallbackFunction
{
virtual void run() { /* ... /* }
}
void registerCppCallback(CallbackFunction * pCB);
You get the point. This way my callbacks have state, I don't need to
mess around with function pointers, my users don't have to even
#include the C-API's headers and I can translate their arguments from
the underlying API's C types to their equivalent STL classes.
My plan was to implement this by creating one "master" callback the C-
way and have it act as a dispatcher to the actual callback
implementations in C++.
The problem is that, with the C API I'm working, the callback
function's signature doesn't specify which function is being called.
So if I register more than one callback with the same master callback
function I have no way of knowing how to dispatch the call. So I'm
stuck basically.
The above code is a simplified version of the actual C interface I'm
working with. If you're interested, the actual API is jsapi (Mozilla's
implementation of Javascript) and what I'm trying to do is use the
JS_DefineFunction call to bridge between Javascript and C++ by
allowing Javascript code to call C++ functions/functors.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
assaflavie (8)
|
7/18/2007 7:00:55 AM |
|
assaf <assaflavie@gmail.com> wrote in news:1184758436.991084.129780
@z24g2000prh.googlegroups.com:
> I'm using a C API (it's actually Spidermonkey's jsapi) with which I
> can register callback functions:
>
> void registerCallback(const char * name, CStyleFunctionPtr callback);
>
> I'm trying to wrap and abstract away this API from my users by
> offering a pure C++ interface, in which users could implement callback
> via functions objects, or something similar. e.g.:
>
> struct FooCallback : public CallbackFunction
> {
> virtual void run() { /* ... /* }
> }
>
> void registerCppCallback(CallbackFunction * pCB);
>
> You get the point. This way my callbacks have state, I don't need to
> mess around with function pointers, my users don't have to even
> #include the C-API's headers and I can translate their arguments from
> the underlying API's C types to their equivalent STL classes.
>
> My plan was to implement this by creating one "master" callback the C-
> way and have it act as a dispatcher to the actual callback
> implementations in C++.
>
> The problem is that, with the C API I'm working, the callback
> function's signature doesn't specify which function is being called.
> So if I register more than one callback with the same master callback
> function I have no way of knowing how to dispatch the call. So I'm
> stuck basically.
I'm a little unclear what you mean here. Wouldn't you be registering
by name?
> The above code is a simplified version of the actual C interface I'm
> working with. If you're interested, the actual API is jsapi (Mozilla's
> implementation of Javascript) and what I'm trying to do is use the
> JS_DefineFunction call to bridge between Javascript and C++ by
> allowing Javascript code to call C++ functions/functors.
>
>
Have a look at Boost/TR1 function:
http://www.boost.org/doc/html/function/tutorial.html#id1186501
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1402.html
Your storage could be something like std::map<std::string,
boost::function<...> > if your functions have the same signature. The
function objects are typesafe and can store all sorts of functions,
including function pointers, functors, and binders.
The JSNative function pointer type was not immediately availabe in a
search, so you'll have to match that.
You could have something like this:
class CallbackMgr
{
typedef CallbackT boost::function<int(int)>; //whatever JSNative is
typedef ContainerT std::map<
std::string,
CallbackT>;
ContainerT container;
public:
// returns true if replacing old value
bool register(const char * name, CallbackT callback)
{
return container.insert(std::make_pair(
std::string(name),
callback)).second;
}
int execute(const char * name, int arg)
{
ContainerT::const_iterator i = container.find(std::string(name));
if (i != container.end) return i->second(arg);
// do not-found error processing here...
}
};
There's a minor drawback: std::string is kind of heavy as a key, so
you might want to look at yasli or Alexandrescu's article on maps with
expensive keys. I doubt you really care.
You'll probably want to wrap all the various types for your own
sanity...
Generally if you have separable or fine-grained callback needs, then
Boost/TR1 function is the way to go. If you have callbacks grouped
together logically and they all should be implemented, then it's
better to group them in a class having virtual functions:
// user must inherit and implement, see Non-Virtual Interface
class CallbackGroup
{
public:
void f1() { f1Imp(); }
.....
void fn() { fnImp(); }
virtual ~CallbackGroup() = 0 { }
private:
virtual void f1Imp() = 0;
.....
virtual void fnImp() = 0;
};
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
W
|
7/18/2007 3:28:38 PM
|
|
assaf wrote:
> I'm using a C API (it's actually Spidermonkey's jsapi) with which I
> can register callback functions:
>
> void registerCallback(const char * name, CStyleFunctionPtr callback);
Two questions here:
1. How does 'CStyleFunctionPtr' look like?
2. What is 'name' used for?
> I'm trying to wrap and abstract away this API from my users by
> offering a pure C++ interface, in which users could implement callback
> via functions objects, or something similar. e.g.:
>
> struct FooCallback : public CallbackFunction
> {
> virtual void run() { /* ... /* }
> }
>
> void registerCppCallback(CallbackFunction * pCB);
>
> You get the point.
Ahem, not really: my first question would be who owns 'pCB' afterwards.
> This way my callbacks have state, I don't need to
> mess around with function pointers,
...instead you mess around with object pointers with unclear ownership?
Seriously, consider either using references or use auto_ptr to make
ownership clear.
> my users don't have to even
> #include the C-API's headers and I can translate their arguments from
> the underlying API's C types to their equivalent STL classes.
>
> My plan was to implement this by creating one "master" callback the C-
> way and have it act as a dispatcher to the actual callback
> implementations in C++.
>
> The problem is that, with the C API I'm working, the callback
> function's signature doesn't specify which function is being called.
> So if I register more than one callback with the same master callback
> function I have no way of knowing how to dispatch the call. So I'm
> stuck basically.
Okay. Typically, a C-style callback interface takes a function pointer and a
void pointers that holds some user-defined context. In you case, it could
only be the 'name', therefore also my initial two questions. If no such
thing is provided, there is nothing you can do. Otherwise, you could either
use the context to map to the object making the request or make the context
a pointer to the object itself.
Uli
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Ulrich
|
7/19/2007 8:55:15 AM
|
|
|
2 Replies
162 Views
(page loaded in 0.252 seconds)
Similiar Articles: glut and (Visual)C++ - comp.graphics.api.openglThe file WmlGlutApplication.cpp shows a variation on the mechanism I described to you. The callback functions are static C-style functions, but they each get a pointer ... Windows API programming with gfortran or g95 - comp.lang.fortran ...If it's required to compile a callback function that ... I updated my Fortran adaptation of Petzold's Hello ... integer(C_INT) cbSize integer(C_INT) style ... strndup: RFC - comp.compilers.lccIt's bad style. The responsibility for deallocation ... hand, defining a decent error handling mechanism for C without ... RFC] Get ... mnc_len); > + if (ret) > + mm_callback ... DSP Job opening in Sacramento, CA - comp.dspStill, in the early phases exposure is probably the main mechanism. My two-and-a-half ... --South Carolina Republican Debate, Feb. 15, 2000 "I've changed my style somewhat ... [comp.publish.cdrom] CD-Recordable FAQ, Part 1/4 - comp.publish ...Archive-name: cdrom/cd-recordable/part1 Posting-Frequency: monthly Last-modified: 2008/10/09 Version: 2.71 Send corrections and updates to And... Adapting a C-style callback mechanism to C++ - RhinocerusI'm using a C API (it's actually Spidermonkey's jsapi) with which I can register callback functions: void registerCallback(const char * name, Callback (computer programming) - Wikipedia, the free encyclopediaIn computer programming, a callback is a reference to a piece of executable code that is ... Continuation-passing style; Signals and slots; Event loop; Event-driven programming Interfacing C++ member functions with C libraries... to-function accepted by a C-style callback. In this contribution we want to develop a mechanism that ... to tackle the problem of adapting member functions to C-style ... .:: C++ Callback Solution - By Arash Partow ::.... passing a class's method as a callback function. In the C ... future in C++ with regards to callback and delegate mechanisms. Callback Functions Tutorial - CodeGuru - Microsoft developers ...XP-Style Menus; Other Controls » Bitmap Buttons; Charting and analogue controls ... Another example from WinAPI functions that use callback mechanism is EnumWindow(), which ... 6/22/2012 8:41:52 AM
|