Adapting a C-style callback mechanism to C++

  • Permalink
  • submit to reddit
  • Email
  • Follow


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

See related articles to this posting


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
comp.lang.c++.moderated 10620 articles. 8 followers. Post

2 Replies
250 Views

Similar Articles

[PageSpeed] 2


  • Permalink
  • submit to reddit
  • Email
  • Follow


Reply:

Similar Artilces:

C Style Callbacks
I do not understand why C style callbacks are not type safe. A callback function must match the function pointer signature specified in the callee. If the signatures are compared at compile time, how is this not type safe? I understand that a function pointer is just an address but if the compiler is capable of checking the use of the callback I don't see how it could not be type safe. Please explain and provide examples. Thanks! Todd Hopfinger [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] Todd...

registering class methods as C style callbacks
consider the following problem: You have a C style library and API that uses callbacks to implement functionality. Examples of this are X11 API, OpenGL/GLUT...The List goes on. The power of virtuals in C++ leads us to want to implement a framework where those callbacks are simply overriden virtual methods in a derived class. So... struct A { A() { ::set_timerroutine(timerroutine); } ~A() { ::clear_timerroutine(); } void timerroutine() { action(); } virtual void action()=0; }; struct B: public A { B(): A() {} action() { // do something relevant here } }; B myT...

Deal with C style function pointer callback in an object
I want to write an class that hide away the function pointer callbacks. That is: Normally i create this function: void errorCallback(char * err_msg) then I call registerErrorCallback(&errorCallback) Then when there is an error in this third party module, my errorCallback function will get called. However, I would like to make this as a clean OO implementation. I face with a problem, how can I pass a function to registerErrorCallback that when call will make some change the state of my object? I got stuck with some singleton-like implementation but I am not sure if this is a good idea....

Mixing pascal-style upp callback functions with C++
How does one mix pascal-style callback functions within a C++ class (or is it even possible)? Let's say I've created a base class for an application object (this is all from scratch, this isn't using PowerPlant or any other framework). I'll want to create an overrideable Open() method so a derived class will open the correct documet type. The code might look something like this: class CApplicationBase { public: CApplicationBase(); virtual ~CApplicationBase(); void Initialize(); virtual void ...

C++ code with C-style interface for a library to be used in C++ and C?
Hi! I have a question about building and then using libraries containing C++ code. Let's say I have some C++ code and a .cpp file with 1 function that uses some other C++ code / classes etc... Also, any possible exception is handled within the function itself. In code: MyModule.h ---------- #ifndef MYMODULE_H #define MYMODULE_H extern int Test(float inParam1,float inParam2,float* outResult); #endif // #ifndef MYMODULE_H MyModule.cpp ------------ #include "MyModule.h" #include "MyClasses.h" // contains MyClassA and MyClassB int Test(float inParam1,float inParam2,...

Callback into C++ from C
I have legacy C code that performs some required functionality. I want to notify my C++ classes after work has been completed in the C code. In otherwords, I need to call a C++ method from C. Some PSEUDO code may help: /* C++ code */ class MyFooClass { public: NotifyHandler(); }; /* C code */ #ifdef __cplusplus extern "C" { #endif void foo() { /* Do some work */ /* finish work */ /* Notify C++ class via callback here */ } #ifdef __cplusplus }; #endif Anonymous wrote: > I have legacy C code that performs some required functionality. I want > to notify...

C style casting or c++
Hi All, ------------- #include <iostream> using namespace std; template<class A, class B, class C> inline A max(B const& num1, C const& num2) { return (A)num1>(A)num2?(A)num1:(A)num2; } How can i implement this template function more c++ style? Any improvement are welcome? phal [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] "phal" <betterdie@gmail.com> schrieb im Newsbeitrag news:1134714493.932934.186340@o13g2000cwo.googlegroups.com... > Hi All, > > ...

Style guides for C and/or C++
I've been searching at this forum and at the Internet for style guides for C and/or C++, and I've found this one: http://www.psgd.org/paul/docs/cstyle/cstyle.htm Also, I've read some threads about C style matters. I think there is really a lot of stuff! I just would like to ask you for a quick answer to this question: which style guide or style rules do you recommend me to use when writing C code? It would be great if many of you would answer, so we all could have here a thread with a good summary about this subject. Thank you for the feed-back!! :-) On Jan 18...

C-style coding in C++
In C++ code of classes, would it be bad to use all those C-runtime functions, for example, strcpy, strlen, strcat, etc.? What are Standard libraries which have the above C functions? istringstream and string? If using those C-runtime, does it mean that the code will also be linked to C-runtime library and C++ libraries? Is there any disadvantage with this? If a source code contains some classes that are not instantiated anywhere in the code, will compilers automatically ignore them automatically? Thanks for your comments! Garma wrote: > In C++ code of classes, would it be bad to u...

Converting from C style struct offset to C++ style member pointer
When I get a struct offset from a C style API as int. I.e.: struct S { int I1; double D1; int I2; }; int offset = offsetof(S, I2); Now in C++ code I would like to convert this offset to a type safe C++ member pointer of type int S::*. Older gcc versions simply accepted a cast, newer version reject the cast. Marcel Hi Marcel % Marcel M´┐Żller wrote: > When I get a struct offset from a C style API as int. I.e.: > > struct S > { int I1; > double D1; > int I2; > }; > > int offset = offsetof(S, I2); > > Now in C++ co...

[ANN] an implementation of signal-slot mechanism for ANSI C, as well as c-lambda or c closure.
I implemented the signal-slot mechanism under ANSI C for my own requirement. Though it is not a 100% general implementation, I think it is suitable for most environment, and it is portable with ease. So I announce it, for any feedback and advice, I'll glad to improve it and hope it gives a hand. Here is the source code: http://c-sigslot.googlecode.com/files/sigslot.zip, include the /boost/preprocessor which is used for macro definition. (it is needed to specify the head files searching path to include the source's root directory when compile the sources) I wrote some words...

C Vs C++ style casts
I have been using C++ style casts for quite sometime, and got used to using it instead of C style casts. Still, in many cases, I felt that using C++ style casts requires typing the long sequence and unfriendly (I am speaking of specific places where using C style casts will be harmless). Consider the example (the isA* functions used here aren't polymorphic and they are provided in derived classes): if (decl->isAFunction() && (!(static_cast<Function *>(decl))->isATemplate() || (static_cast<Function *>(decl))->isAInstantiatedTemplate())) I know that it is safe...

Callbacks From C++ or C# from within Matlab
Hi, I have the following problem; I have a c++/c# application attached to matlab, i want to catch a callback from matlab into my c++/c#. How would I do that? Regards "Iskandar Prins" <iskandarprins@gmail.com> wrote in message news:77ac5431-b107-414e-8e86-3f83170a7388@e27g2000yqd.googlegroups.com... > Hi, > > I have the following problem; > > I have a c++/c# application attached to matlab, i want to catch a > callback from matlab into my c++/c#. How would I do that? So you want a graphics callback to call your C++/C# application? Inside the callback fu...

How to implement set_trace_func callback in C/C++?
Hello everybody, I'm trying to implement the callback for set_trace_func in C++. Think of it as C if thats any easier. Shown at the bottom of this posting is my sample application which runs the standard "Hello World" ruby program. My callback function "my_trace_function" gets called. Problem is I don't know how to access the event, file, line, id, binding and classname parameters passed to the function which I'd have access to if coding in Ruby. Can anyone tell me how to get the parameters passed to the callback function? Have I got the function prototype co...

passing c++ methods as c-callbacks
Hi folks, after reading several threads on this issue (-> subject) I fear that I got a problem that cannot easily be solved by the offered workarounds in an acceptable way, at least not with my limited c & c++ experience. Maybe some of you can help. the problem: I need several instances of a class whose (non-static!) methods should serve as callbacks for a dll (which can' be manipulated/adapted in any way). Static use is inacceptable and won't work for my setup because I'm in desperate need for several independent working instances of the same class. The actual problem i...

Using C++ namespaces in C# namespace style
Is is OK to use C++ namespaces like namespaces are used in C#? Namely, to hierarchically organize code. For example: std::File std::Container ...

Search and replace c-style strings in c++
I am trying to write a function that takes three c-style strings, and returns a c-style string. This function searches a c-string for all occurrences of the sub-string and replaces them with a different string. This program works but seems very inelegant. I can't help the feeling like it could have been done in a less bulky way. #include <iostream> #include <cstring> using namespace std; int main() { char* replaceSubstring(char*,char*,char*); char *string1, *string2, *string3; string1 = "the dog jumped over the fence"; string2 = "the"; string3 = "...

Problem calling a C function from a C++ callback
Hello, I am having a weird problem with Visual C++ 2008 Express. I have a C++ callback called from a C library. This callback calls code from that library, but the arguments are lost. Here is some code demonstrating the problem: // Function is declared static in the class definition // DeviceRef is an opaque C type (a pointer to a struct) void TestComponent::libraryCallback (void * refCon, const DeviceRef device, const Event event) { assert (device); // here device is not NULL, but inside the next call, device is NULL DeviceDoSomething (device); } I don't understand why inside &quo...

Do I need the C-style struct instantiation in C++ at all?
Hi, I'm using a glibc system header <sys/stat.h> which defines a C struct 'stat'. Furthermore, I'm using the struct 'dirent', defined in <dirent.h>. Now, at one point in my code I'm holding an std::list of dirents: std::list< dirent > mylist; This works. Now, I wanted to extend the list to hold pairs of dirent/stat: std::list< std::pair< dirent, stat > > mynewlist; Now, the compiler (g++ 3.3.4) says he doesn't know a type called 'stat'. So I tried the C-style notation for instantiating structs: std::list&...

C++ callback function passed to a C program
Hi all, is there any trouble setting an C++ static class method as callback function for a C program or library ? Thanks Eric Entressangle wrote: > Hi all, > > is there any trouble setting an C++ static class method as callback > function for a C program or library ? Yes. The function will have C++ calling conventions, but be called using C calling conventions. An some (many?) compilers, they are both the same, but if they differ, it won't work. For maximum portability, you should only use extern "C" functions for that, which is of course not possible for member...

encapsulate C callback function into a C++ class
Hi, I have developped an MFC program that uses a fingerprint scanner. To control the Bio scanner I use a library with the following function these functions are used to get the status message from the scanner T__STATUS SM_BSP_SetFingerStatus(T__STATUS i_nStatus, T__UCHAR *i_pImage, T__ULONG i_nRow, T__ULONG i_nCol, T__BOOL *o_pContinue) { } T__STATUS SM_BSP_SetMsgInfos(T__INT i_nMsgId, T__BOOL *o_pContinue) { } T__STATUS SM_BSP_SetBSPStatus(T__UCHAR i_nStatusId, T__BOOL *o_pContinue) { } l_GUICallbackFunctions.SM_BSP_SetFingerStatus=(PSM_BSP_SET_FINGER_STATUS) &SM_BSP_SetFinger...

Setting a C++ function as callback to a C Function!
Hi All, I have a C interface which takes a C function pointer as input for setting callback. Now, I want to set a C++ function for the same. I am getting a calling convention error. Is it possible for me to do this? Any pointers in that direction would be of great help. Thanks in Advance! Regards, Jayaraghavendran.K On 19 Jan., 19:36, Jay <jayaraghavend...@gmail.com> wrote: > Hi All, > > I have a C interface which takes a C function pointer as input for > setting callback. Now, I want to set a C++ function for the same. > > I am getting a calling convention error...

Passing C-style flags to C subprograms
Hello, I have been trying to write an Ada binding to libevent2. There are all sorts of issues and I have only started, so I'm not sure it will ever lead to anything interesting, except for my own personal enlightenment. One of these issues is passing and retrieving "C-style" flags, and I would love to see sharing of insights on this topic. I guess "C-style flags" could be defined as a set of boolean values represented on the least significant of a machine word, and manipulated as "int" values (or sometimes "unsigned" or "unsigned long"). ...

Is static_cast really as fast as C/C++ style casts?
Hi all. In short, is there any performance difference between: float f = 10.0f; int i = static_cast<int>(f); and float f = 10.0f; int i = int(f); I've been meaning to ask this for a while but just how fast is static_cast? I had always assumed (without proof) that static_cast is implemented as a template which just wraps a C/C++ style cast.But then it the Josuttis book it says: "The conversion is allowed only if a type conversion is defined" Presumably then this test is done at compile time? Also, if static_cast is just a wrapper around C/C++ casts then how does it di...