[Please do not mail me a copy of your followup]
Lane <
software.resea...@gmail.com> spake the secret code
<
mkjda...@news3.newsguy.com> thusly:
>I'm using a C api within the C++ MyClass. This works, but I'd like to be
>able to use the private fields (varX) within these callbacks. Is there
>anyway to make the callbacks look like class member functions?
C style callback APIs usually have a void* parameter named something
like "user context" that is registered with the callback function.
This opaque pointer value will be passed to the callback function when
it is invoked.
The typical adaptation of this to a C++ class is to have the class
delcare a static method and register the static method as the callback
with the 'this' pointer as the context argument. The static method
casts the void* user context pointer back to the appropriate type and
then immediately delegates to an instance method.
The static method does not have to be declared extern "C" because
noone is linking to it from a C source file; it is linked within a C++
source file.
Example:
==== Makefile
callback: callback.o main.o
g++ -o callback $^
main.c: callback.h
callback.cpp: callback.h
==== callback.h
#if !defined(CALLBACK_H)
#define CALLBACK_H
typedef void callback_fn_t(void *context);
#if defined(__cplusplus)
extern "C"
{
#endif
extern void register_callback(callback_fn_t *cb, void *user);
extern void register_user_callbacks();
#if defined(__cplusplus)
}
#endif
#endif
==== main.c
#include "callback.h"
callback_fn_t *callback;
void *context;
void register_callback(callback_fn_t *cb, void *user)
{
callback = cb;
context = user;
}
int main()
{
register_user_callbacks();
(*callback)(context);
return 0;
}
==== callback.cpp
#include "callback.h"
#include <iostream>
namespace
{
class Callback
{
public:
void register_callbacks();
private:
static void callback_handler(void *context);
void callback();
};
void Callback::register_callbacks()
{
register_callback(callback_handler, this);
}
void Callback::callback_handler(void *context)
{
static_cast<Callback *>(context)->callback();
}
void Callback::callback()
{
std::cout << "The callback was invoked.\n";
}
Callback long_lived_object;
} // namespace
extern "C"
void register_user_callbacks()
{
long_lived_object.register_callbacks();
}
--
"The Direct3D Graphics Pipeline" free book <
http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <
http://computergraphicsmuseum.org>
The Terminals Wiki <
http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <
http://legalizeadulthood.wordpress.com>
--
"The Direct3D Graphics Pipeline" free book <
http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <
http://computergraphicsmuseum.org>
The Terminals Wiki <
http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <
http://legalizeadulthood.wordpress.com>