I've got an .h file containing 2 different functions declaration:
#ifdef MY_HEADER
#define MY_HEADER
void a();
void b();
#endif
Now into .cpp file I want to implement those functions as different instances of another templated function:
#include "my_header.h"
namespace {
template<size_t N>
void c()
{
...
}
}
void (*a)() = c<42>;
void (*b)() = c<265>;
I'm getting an error message error: 'void (* a)()' redeclared as different kind of symbol. I've also tried a = c<42> and auto a = c<42> with no luck.
I know I can do it like this:
void a() {c<42>();}
void b() {c<265>();}
and I'm almost sure compiler will optimize this extra function call for me, but I'm wondering if there's a better way to declare this. I don't want to put c function itself into .h file either because this function is quite heavy and I don't want to have it recompiled in every source file using my header.
You just need to have the declarations of a and b match the definitions, so declare them as void(*)() variables, rather than void() functions.
The other answers suggesting std::function<void()> are ignoring that it is a very heavyweight option.
my_header.h
#ifdef MY_HEADER
#define MY_HEADER
extern void (*a)();
extern void (*b)();
#endif
my_impl.cpp
#include "my_header.h"
namespace {
template<size_t N>
void c()
{
...
}
}
void (*a)() = c<42>;
void (*b)() = c<265>;
See it live
You may want to forbid a and b from being modified, and declare them as void (* const)(), i.e. (const pointer) to (function).
extern void (* const a)();
...
void (* const a)() = c<42>;
...
// a = c<53>; // error: assignment of read-only variable 'a'
You can do the following:
Header file:
#ifndef MY_HEADER
#define MY_HEADER
#include <functional>
extern std::function<void()> a;
extern std::function<void()> b;
#endif
Implementation file:
#include "Header.h"
namespace {
template<size_t N>
void c() {
...
}
}
std::function<void()> a = std::bind(&c<42>);
std::function<void()> b = std::bind(&c<265>);
I'm wondering if there's a better way to declare this.
If you're looking for a more general-purpose higher wrapper for a function type, use std::function.
In your .h file, declare:
#include <functional>
std::function<void()> a;
In your .cpp file, assign your desired function to it:
a = c<42>;
a();
Be sure about the overhead of using std::function though, it can be quite expensive for such a trivial job.
This is working for me, might be a solution:
header.h
template<size_t N>
void c() {
...
}
main.cpp
#include "header.h"
void (*a)(void) = c<10>;
int main() {
a();
}
Related
[UPDATE] a reproducible example
By splitting declaration and definition into different files, my toy code built without problem...
my main.cpp
#include <iostream>
#include "file0.h"
#include "file1.h"
#include "file2.h"
int main() {
test a;
double b = a.get_recipocal(2.0);
double c = a.get_sqrt(2.0);
std::cout << "b = " << b << std::endl;
std::cout << "c = " << c << std::endl;
return 0;
}
my file0.h
#ifndef TEST_MULTI_FILES_FILE0_H
#define TEST_MULTI_FILES_FILE0_H
class test {
private:
double a;
public:
double get_recipocal(int a);
double get_sqrt(int a);
};
#endif//TEST_MULTI_FILES_FILE0_H
my file1.h
#ifndef TEST_MULTI_FILES_FILE1_H
#define TEST_MULTI_FILES_FILE1_H
double test::get_recipocal(int a) {
return 1. / a;
}
#endif//TEST_MULTI_FILES_FILE1_H
my file2.h
#include <cmath>
#ifndef TEST_MULTI_FILES_FILE2_H
#define TEST_MULTI_FILES_FILE2_H
double test::get_sqrt(int a) {
return sqrt(a);
}
#endif//TEST_MULTI_FILES_FILE2_H
Built and run without problem. So it is not an obvious error in my production code
Thanks!
(below are original question)
I am new to C++ classes, here is my problem
for example, I have a class in file b0.h
class B::virtual public A {
void func1() {
some work1;
}
void func2() {
some work2;
}
...
};
Now I want to move the implementation of func2() into an other header file, say b1.h
so I did the following:
#include "path/to/b0.h"
void B::func2(){
some work2;
}
But the compiler will complain
use of undeclared identifier 'B'
void B::func2() {
^
(I also tested the following: in b0.h, I included b1.h and if I made func2() in b1.h a static function, I can call it from b0.h without problem.)
The goal is to separate members of B into two header files, each one contain one function implementation (I want to have a side-by-side comparison between func1 and func2 in different file, they are similar and very long). I feel this is a very common scenario, but I didn't find a good example. Is there an obvious mistake? Thank you!
What you want to do is quite common if you have larger classes. What you need is one header file with all the declarations, say b.h:
#include "path/to/a.h"
class B : virtual public A { // : instead of ::
void func1(); // return type, no function body
void func2(); // return type, no function body
};
Then you can split the definitions (the actual implementation) over as many source files as you wish. For example file b_func1.cpp might contain the definition for B::func1
#include "path/to/b.h"
void B::func1() { /* some code */ }
And file b_func2.cpp might contain the definition for B::func2
#include "path/to/b.h"
void B::func2() { /* some code */ }
Anyway, only in specific cases (like templates or inline functions) the definition can be in a header. It may work as long as you include every header only once, but it's still wrong, so put the definitions in a translation unit / source file.
The goal is to allow header files to "register" an initializer function so that main can just iterate over those functions and call them. I've stumbled upon a solution which uses __attribute__, but it seems to be GCC-only (https://stackoverflow.com/a/37082249/7867841).
// header1.h
void myInitializer(){}
REGISTER_THIS(&myInitializer);
// header2.h
void myInitializer2(){}
REGISTER_THIS(&myInitializer2);
// main.cpp
...
for_each_registered_ptr(){ call_ptr(); } // calls myInitializer and myInitializer2
...
Is there a universal solution to this? Functions can be switched with classes or types if that's easier to implement.
You can abuse static function locals to do this, avoiding the static initialization order fiasco.
In init.h, we have this:
#ifndef INIT_H
#define INIT_H
#include <vector>
// Can be changed to std::function<...> or whatever you need.
typedef void (*init_fn)();
// Returns int so it can easily be used in a variable initializer.
int register_initializer(init_fn fn);
std::vector<init_fn> & get_initializers();
#endif
Then, in init.cpp:
#include "init.h"
int register_initializer(init_fn fn)
{
get_initializers().push_back(fn);
return 0;
}
std::vector<init_fn> & get_initializers()
{
static std::vector<init_fn> ip;
return ip;
}
A few notes, before we move on to the rest:
The static local is only initialized once, the first time the function is called.
The "global" vector is kind-of-leaked. It's unlikely this will be a problem unless you are adding tens of thousands of entries to this vector. You can always get_initializers().clear() to empty it out after using it.
We'd use it like so, in a.cpp:
#include <iostream>
#include "init.h"
static void a_init() { std::cout << "a_init()\n"; }
static auto dummy = register_initializer(a_init);
And, finally, we have our (rather simple) main.cpp:
#include "init.h"
int main() {
for (auto fn : get_initializers()) {
fn();
}
return 0;
}
Trying to create a class which acts as a tool to amplify/attenuate some value based on lookup tables.
Foo.h
#ifndef FOO_H
#define FOO_H
#include <array>
#include <limits>
class Foo
{
public:
Foo();
~Foo();
static double applySomeFoo(double f, unsigned int amplify_by);
private:
static constexpr int m_BITS_IN_INT {std::numeric_limits<int>.digits};
static std:array<double, m_BITS_IN_INT> m_fooFactors /***?** Don't know what to put here! */;
// **?** Tried {{}}, {} and nothing and {{...}} and {...} and {{{}}} then scratched head...
};
#endif
Foo.cpp
#include <assert>
#include "Foo.h"
double Foo::applySomeFoo(double f, unsigned int amplify_by)
{
assert(amplify_by < Foo::m_BITS_IN_INT);
return (f * Foo::m_fooFactors.at(amplify_by));
}
// FOO
Foo::Foo() : /**?** Don't know what to put here! */
{
// ctor
// Populate the lookup table
int i {0};
for(auto &x : Foo::m_fooFactors)
{
x = static_cast<double>(2 ^ i++);
}
}
Foo::~Foo()
{
// dtor
}
I'm new to C++.
It fails to compile and I don't really understand how to instantiate so I can then populate the static array with values since it has a compile-time-variable length.
So the question boils down to;
Q. How can I ensure m_fooFactors is an instantiation of an array of zeros of the known fixed-length so I can then populate it in the class constructor?
This EXAMPLE is a toy re. the m_fooFactors calculation, the actual calc is more complex, but gives you a flavor of my usage of the std::array as lookup-table.
I am using GCC and trying to make C++11 code.
I would be grateful for any help.
Let's say we have a C++ library with a class like this:
class TheClass {
public:
TheClass() { ... }
void magic() { ... }
private:
int x;
}
Typical usage of this class would include stack allocation:
TheClass object;
object.magic();
We need to create a C wrapper for this class. The most common approach looks like this:
struct TheClassH;
extern "C" struct TheClassH* create_the_class() {
return reinterpret_cast<struct TheClassH*>(new TheClass());
}
extern "C" void the_class_magic(struct TheClassH* self) {
reinterpret_cast<TheClass*>(self)->magic();
}
However, it requires heap allocation, which is clearly not desired for such a small class.
I'm searching for an approach to allow stack allocation of this class from C code. Here is what I can think of:
struct TheClassW {
char space[SIZEOF_THECLASS];
}
void create_the_class(struct TheClassW* self) {
TheClass* cpp_self = reinterpret_cast<TheClass*>(self);
new(cpp_self) TheClass();
}
void the_class_magic(struct TheClassW* self) {
TheClass* cpp_self = reinterpret_cast<TheClass*>(self);
cpp_self->magic();
}
It's hard to put real content of the class in the struct's fields. We can't just include C++ header because C wouldn't understand it, so it would require us to write compatible C headers. And this is not always possible. I think C libraries don't really need to care about content of structs.
Usage of this wrapper would look like this:
TheClassW object;
create_the_class(&object);
the_class_magic(&object);
Questions:
Does this approach have any dangers or drawbacks?
Is there an alternative approach?
Are there any existing wrappers that use this approach?
You can use placement new in combination of alloca to create an object on the stack. For Windows there is _malloca. The importance here is that alloca, and malloca align memory for you accordingly and wrapping the sizeof operator exposes the size of your class portably. Be aware though that in C code nothing happens when your variable goes out of scope. Especially not the destruction of your object.
main.c
#include "the_class.h"
#include <alloca.h>
int main() {
void *me = alloca(sizeof_the_class());
create_the_class(me, 20);
if (me == NULL) {
return -1;
}
// be aware return early is dangerous do
the_class_magic(me);
int error = 0;
if (error) {
goto fail;
}
fail:
destroy_the_class(me);
}
the_class.h
#ifndef THE_CLASS_H
#define THE_CLASS_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
class TheClass {
public:
TheClass(int me) : me_(me) {}
void magic();
int me_;
};
extern "C" {
#endif
size_t sizeof_the_class();
void *create_the_class(void* self, int arg);
void the_class_magic(void* self);
void destroy_the_class(void* self);
#ifdef __cplusplus
}
#endif //__cplusplus
#endif // THE_CLASS_H
the_class.cc
#include "the_class.h"
#include <iostream>
#include <new>
void TheClass::magic() {
std::cout << me_ << std::endl;
}
extern "C" {
size_t sizeof_the_class() {
return sizeof(TheClass);
}
void* create_the_class(void* self, int arg) {
TheClass* ptr = new(self) TheClass(arg);
return ptr;
}
void the_class_magic(void* self) {
TheClass *tc = reinterpret_cast<TheClass *>(self);
tc->magic();
}
void destroy_the_class(void* self) {
TheClass *tc = reinterpret_cast<TheClass *>(self);
tc->~TheClass();
}
}
edit:
you can create a wrapper macro to avoid separation of creation and initialization. you can't use do { } while(0) style macros because it will limit the scope of the variable. There is other ways around this but this is highly dependent on how you deal with errors in the code base. A proof of concept is below:
#define CREATE_THE_CLASS(NAME, VAL, ERR) \
void *NAME = alloca(sizeof_the_class()); \
if (NAME == NULL) goto ERR; \
// example usage:
CREATE_THE_CLASS(me, 20, fail);
This expands in gcc to:
void *me = __builtin_alloca (sizeof_the_class()); if (me == __null) goto fail; create_the_class(me, (20));;
There are alignment dangers. But maybe not on your platform. Fixing this may require platform specific code, or C/C++ interop that is not standardized.
Design wise, have two types. In C, it is struct TheClass;. In C++, struct TheClass has a body.
Make a struct TheClassBuff{char buff[SIZEOF_THECLASS];};
TheClass* create_the_class(struct TheClassBuff* self) {
return new(self) TheClass();
}
void the_class_magic(struct TheClass* self) {
self->magic();
}
void the_class_destroy(struct TheClass* self) {
self->~TheClass();
}
C is supposed to make the buff, then create a handle from it and interact using it. Now usually that isn't required as reinterpreting pointer to theclassbuff will work, but I think that is undefined behaviour technically.
Here is another approach, which may or may not be acceptable, depending on the application specifics. Here we basically hide the existence of TheClass instance from C code and encapsulate every usage scenario of TheClass in a wrapper function. This will become unmanageable if the number of such scenarios is too large, but otherwise may be an option.
The C wrapper:
extern "C" void do_magic()
{
TheClass object;
object.magic();
}
The wrapper is trivially called from C.
Update 2/17/2016:
Since you want a solution with a stateful TheClass object, you can follow the basic idea of your original approach, which was further improved in another answer. Here is yet another spin on that approach, where the size of the memory placeholder, provided by the C code, is checked to ensure it is sufficiently large to hold an instance of TheClass.
I would say that the value of having a stack-allocated TheClass instance is questionable here, and it is a judgement call depending on the application specifics, e.g. performance. You still have to call the de-allocation function, which in turn calls the destructor, manually, since it is possible that TheClass allocates resources that have to be released.
However, if having a stack-allocated TheClass is important, here is another sketch.
The C++ code to be wrapped, along with the wrapper:
#include <new>
#include <cstring>
#include <cstdio>
using namespace std;
class TheClass {
public:
TheClass(int i) : x(i) { }
// cout doesn't work, had to use puts()
~TheClass() { puts("Deleting TheClass!"); }
int magic( const char * s, int i ) { return 123 * x + strlen(s) + i; }
private:
int x;
};
extern "C" TheClass * create_the_class( TheClass * self, size_t len )
{
// Ensure the memory buffer is large enough.
if (len < sizeof(TheClass)) return NULL;
return new(self) TheClass( 3 );
}
extern "C" int do_magic( TheClass * self, int l )
{
return self->magic( "abc", l );
}
extern "C" void delete_the_class( TheClass * self )
{
self->~TheClass(); // 'delete self;' won't work here
}
The C code:
#include <stdio.h>
#define THE_CLASS_SIZE 10
/*
TheClass here is a different type than TheClass in the C++ code,
so it can be called anything else.
*/
typedef struct TheClass { char buf[THE_CLASS_SIZE]; } TheClass;
int do_magic(TheClass *, int);
TheClass * create_the_class(TheClass *, size_t);
void delete_the_class(TheClass * );
int main()
{
TheClass mem; /* Just a placeholder in memory for the C++ TheClass. */
TheClass * c = create_the_class( &mem, sizeof(TheClass) );
if (!c) /* Need to make sure the placeholder is large enough. */
{
puts("Failed to create TheClass, exiting.");
return 1;
}
printf("The magic result is %d\n", do_magic( c, 232 ));
delete_the_class( c );
return 0;
}
This is just a contrived example for illustration purposes. Hopefully it is helpful. There may be subtle problems with this approach, so testing on your specific platform is highly important.
A few additional notes:
THE_CLASS_SIZE in the C code is just the size of a memory buffer in which
a C++'s TheClass instance is to be allocated; we are fine as long as
the size of the buffer is sufficient to hold a C++'s TheClass
Because TheClass in C is just a memory placeholder, we might just as
well use a void *, possibly typedef'd, as the parameter type in the
wrapper functions instead of TheClass. We would reinterpret_cast
it in the wrapper code, which would actually make the code clearer:
pointers to C's TheClass are essentially reinterpreted as C++'s TheClass anyway.
There is nothing to prevent C code from passing a TheClass* to the
wrapper functions that doesn't actually point to a C++'s TheClass
instance. One way to solve this is to store pointers to properly
initialized C++ TheClass instances in some sort of a data structure
in the C++ code and return to the C code handles that can be used to
look up these instances.
To use couts in the C++ wrapper we need to link with
the C++ standard lib when building an executable. For example, if
the C code is compiled into main.o and C++ into lib.o, then on
Linux or Mac we'd do gcc -o junk main.o lib.o -lstdc++.
It worth to keep each piece of knowledge in a single place, so I would suggest to make a class code "partially readable" for C. One may employ rather simple set of macro definitions to enable it to be done in short and standard words. Also, a macro may be used to invoke constructor and destructor at the beginning and the end of stack-allocated object's life.
Say, we include the following universal file first into both C and C++ code:
#include <stddef.h>
#include <alloca.h>
#define METHOD_EXPORT(c,n) (*c##_##n)
#define CTOR_EXPORT(c) void (c##_construct)(c* thisPtr)
#define DTOR_EXPORT(c) void (c##_destruct)(c* thisPtr)
#ifdef __cplusplus
#define CL_STRUCT_EXPORT(c)
#define CL_METHOD_EXPORT(c,n) n
#define CL_CTOR_EXPORT(c) c()
#define CL_DTOR_EXPORT(c) ~c()
#define OPT_THIS
#else
#define CL_METHOD_EXPORT METHOD_EXPORT
#define CL_CTOR_EXPORT CTOR_EXPORT
#define CL_DTOR_EXPORT DTOR_EXPORT
#define OPT_THIS void* thisPtr,
#define CL_STRUCT_EXPORT(c) typedef struct c c;\
size_t c##_sizeof();
#endif
/* To be put into a C++ implementation coce */
#define EXPORT_SIZEOF_IMPL(c) extern "C" size_t c##_sizeof() {return sizeof(c);}
#define CTOR_ALIAS_IMPL(c) extern "C" CTOR_EXPORT(c) {new(thisPtr) c();}
#define DTOR_ALIAS_IMPL(c) extern "C" DTOR_EXPORT(c) {thisPtr->~c();}
#define METHOD_ALIAS_IMPL(c,n,res_type,args) \
res_type METHOD_EXPORT(c,n) args = \
call_method(&c::n)
#ifdef __cplusplus
template<class T, class M, M m, typename R, typename... A> R call_method(
T* currPtr, A... args)
{
return (currPtr->*m)(args...);
}
#endif
#define OBJECT_SCOPE(t, v, body) {t* v = alloca(t##_sizeof()); t##_construct(v); body; t##_destruct(v);}
Now we can declare our class (the header is useful both in C and C++, too)
/* A class declaration example */
#ifdef __cplusplus
class myClass {
private:
int y;
public:
#endif
/* Also visible in C */
CL_STRUCT_EXPORT(myClass)
void CL_METHOD_EXPORT(myClass,magic) (OPT_THIS int c);
CL_CTOR_EXPORT(myClass);
CL_DTOR_EXPORT(myClass);
/* End of also visible in C */
#ifdef __cplusplus
};
#endif
Here is the class implementation in C++:
myClass::myClass() {std::cout << "myClass constructed" << std::endl;}
CTOR_ALIAS_IMPL(myClass);
myClass::~myClass() {std::cout << "myClass destructed" << std::endl;}
DTOR_ALIAS_IMPL(myClass);
void myClass::magic(int n) {std::cout << "myClass::magic called with " << n << std::endl;}
typedef void (myClass::* myClass_magic_t) (int);
void (*myClass_magic) (myClass* ptr, int i) =
call_method<myClass,myClass_magic_t,&myClass::magic,void,int>;
and this is a using C code example
main () {
OBJECT_SCOPE(myClass, v, {
myClass_magic(v,178);
})
}
It's short and working! (here's the output)
myClass constructed
myClass::magic called with 178
myClass destructed
Note that a variadic template is used and this requires c++11. However, if you don't want to use it, a number of fixed-size templates ay be used instead.
Here's how one might do it safely and portably.
// C++ code
extern "C" {
typedef void callback(void* obj, void* cdata);
void withObject(callback* cb, void* data) {
TheClass theObject;
cb(&theObject, data);
}
}
// C code:
struct work { ... };
void myCb (void* object, void* data) {
struct work* work = data;
// do whatever
}
// elsewhere
struct work work;
// initialize work
withObject(myCb, &work);
What I did in alike situation is something like:
(I omit static_cast, extern "C")
class.h:
class TheClass {
public:
TheClass() { ... }
void magic() { ... }
private:
int x;
}
class.cpp
<actual implementation>
class_c_wrapper.h
void* create_class_instance(){
TheClass instance = new TheClass();
}
void delete_class_instance(void* instance){
delete (TheClass*)instance;
}
void magic(void* instance){
((TheClass*)instance).magic();
}
Now, you stated that you need stack allocation. For this I can suggest rarely used option of new: placement new. So you'd pass additional parameter in create_class_instance() that is pointing to an allocated buffer enough to store class instance, but on stack.
This is how I would solve the issue (basic idea is to let interprete C and C++ the same memory and names differently):
TheClass.h:
#ifndef THECLASS_H_
#define THECLASS_H_
#include <stddef.h>
#define SIZEOF_THE_CLASS 4
#ifdef __cplusplus
class TheClass
{
public:
TheClass();
~TheClass();
void magic();
private:
friend void createTheClass(TheClass* self);
void* operator new(size_t, TheClass*) throw ();
int x;
};
#else
typedef struct TheClass {char _[SIZEOF_THE_CLASS];} TheClass;
void create_the_class(struct TheClass* self);
void the_class_magic(struct TheClass* self);
void destroy_the_class(struct TheClass* self);
#endif
#endif /* THECLASS_H_ */
TheClass.cpp:
TheClass::TheClass()
: x(0)
{
}
void* TheClass::operator new(size_t, TheClass* self) throw ()
{
return self;
}
TheClass::~TheClass()
{
}
void TheClass::magic()
{
}
template < bool > struct CompileTimeCheck;
template < > struct CompileTimeCheck < true >
{
typedef bool Result;
};
typedef CompileTimeCheck< SIZEOF_THE_CLASS == sizeof(TheClass) >::Result SizeCheck;
// or use static_assert, if available!
inline void createTheClass(TheClass* self)
{
new (self) TheClass();
}
extern "C"
{
void create_the_class(TheClass* self)
{
createTheClass(self);
}
void the_class_magic(TheClass* self)
{
self->magic();
}
void destroy_the_class(TheClass* self)
{
self->~TheClass();
}
}
The createTheClass function is for friendship only - I wanted to avoid the C wrapper functions to be publicly visible within C++. I caught up the array variant of the TO, because I consider this better readable than the alloca approach. Tested with:
main.c:
#include "TheClass.h"
int main(int argc, char*argv[])
{
struct TheClass c;
create_the_class(&c);
the_class_magic(&c);
destroy_the_class(&c);
}
I have a C library function that expects a function pointer for callback, and I want to pass in a C++ member function. The C++ function modifies a member variable, so I can't use a static free function (as suggested in several similar posts). My attempt (shown below) fails with a compiler error.
This post comes closest to what I need:
Using a C++ class member function as a C callback function
How can I do this without static functions? Thanks!
test.h
#ifndef TEST_H_
#define TEST_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*handler_t)(int foo, void *bar);
void set_handler(handler_t h);
#ifdef __cplusplus
}
#endif
#endif
test.c
#include "test.h"
#include <stdlib.h>
static handler_t handler_ = NULL;
void set_handler(handler_t h) {
handler_ = h;
}
void handle_event(int foo, void *bar) {
if (handler_ != NULL) handler_(foo, bar);
}
test.cpp
#include "test.h"
#include <iostream>
using namespace std;
class Foo {
public:
Foo() : ctr_(0) {};
// handler needs to access non-static variable, so it can't be static
void handler(int foo, void *bar) { ++ctr_; }
private:
int ctr_;
};
int main(int argc, char **argv) {
// error: can't convert to "void (*)(int, void*)"
set_handler(&Foo::handler);
cout << "done" << endl;
return 0;
}
GCC barf
$ gcc test.cpp test.c
test.cpp: In function ‘int main(int, char**)’:
test.cpp:18: error: cannot convert ‘void (Foo::*)(int, void*)’ to ‘void (*)(int, void*)’ for argument ‘1’ to ‘void set_handler(void (*)(int, void*))’
It is not possible, at least with that handler_t signature.
While you can create a free function on your .cpp to wrap the member call, you need a pointer to the Foo instance:
void my_wrap(int foo, void* bar) {
Foo* some_foo_instance = ...;
some_foo_instance->handler(foo, bar);
}
int main(int argc, char **argv) {
set_handler(&my_wrap);
}
You need some void* to pass the Foo instance as a handler attribute:
// Header
typedef void (*handler_t)(int foo, void *bar, void* arg1);
void set_handler(handler_t h, void* arg1);
// Impl.
void set_handler(handler_t h, void* arg1) {
handler_ = h;
handler_arg1_ = arg1;
}
// cpp
void my_wrap(int foo, void* bar, void* arg1) {
Foo* some_foo_instance = static_cast<Foo*>(arg1);
some_foo_instance->handler(foo, bar);
}
// main
int main(int argc, char **argv) {
Foo some_concrete_instance;
set_handler(&my_wrap, static_cast<void*>(&some_concrete_instance));
}
The big question is how many times you need to call set_handler multiple times to call methods on different objects. If this answer is one, you can do something like this:
#include <boost/function.hpp>
class HandlerContext
{
static boost::function<void (int, void*)> s_func
static void forward(int foo, void* bar)
{
s_func(foo, bar);
}
public:
static void set(boost::function<int, void*> const& f)
{
s_func = f;
set_handler(&HandlerContext::forward);
}
};
If the answer is "more than once", you can have multiple forwarding functions that get their function objects out of an array. You will need to preassign slots in this case, because the function in use will indicate which callback to make.
This sentence:
I have a C library function
This means you can NOT pass it any C++ object.
If the library you are using is a C library it does not know about C++ so it can not using anything that is C++ it can only use C stuff.
You MUST make it call a free function in you code.
Now your free function can then call a method on an object (that is why C callbacks have a void* parameter (so you can pass context to the callback)).
Suppose you create a mapping function:
Foo *inst = // some instance of Foo you're keeping around...
void wrapper(int foo, void *bar){
inst->handler(foo, bar);
}
Then use wrapper as the callback. Instance semantics in a callback are kind of strange, so I'm not sure how you're going to be sure you bind to the correct instance -- if this is a singleton maybe that doesn't matter.
Here is an ugly hack I invented awhile ago to solve this problem:
#include <boost/function.hpp>
#include <boost/bind.hpp>
using ::boost::function;
using ::boost::bind;
typedef int (*callback_t)(const char *, int);
typedef function<int(const char *, int)> MyFTWFunction;
template <MyFTWFunction *callback>
class callback_binder {
public:
static int callbackThunk(const char *s, int i) {
return (*callback)(s, i);
}
};
extern void register_callback(callback_t f);
int random_func(const char *s, int i)
{
if (s && *s) {
return i;
} else {
return -1;
}
}
MyFTWFunction myfunc;
class FooClass {
public:
virtual int callme(const char *s, int x) { return 0; };
};
int main(int argc, const char *argv[])
{
FooClass foo;
myfunc = bind(&FooClass::callme, &foo, _1, _2);
register_callback(&callback_binder<&myfunc>::callbackThunk);
return 0;
}
This could probably be fixed to use stuff from TR1 and remove the dependency on Boost.
And also, of course, myfunc is a global variable. It has to be a global variable. You must have one global variable per different possible object you'd want to call back into. OTOH, you can have as many of these globals as you want.
The main issue here is that it is absolutely impossible to do what you want within the given constraints. The pointer to the object you want to call back into has to come from somewhere. In some languages (like Python for example) you can create a function on-the-fly that has it's own copy of the object pointer. This cannot be done in C++. All functions must exist completely at compile time. You cannot create new function instances at run time.
With C++0x, you can sort of create functions at runtime with lambda functions. But these functions have an unspecified type and there is absolutely no way you could ever then pass them to a C function and have it work. Lambda expressions are meant to be supplied as template parameters and it's pretty hard to use them for anything else because their address can't be taken, and even if it could you ccouldn't actually know what type the pointer is pointing to.
I highly recommend not using it. The little void * most callback interfaces allow you to specify that gets handed back to you along with the data is meant to hold an object pointer of some kind. If possible, you should be doing that instead.
If you have control over how handler is defined, I recommend using Boost function objects instead of function pointers.
If you HAVE to use function pointers, define handler_t with an extra void* whose value is passed along with the handler, watch out for the gotchas Martin York linked in a comment. Then you have something like this:
typedef void (*handler_t)(int foo, void *bar, void *data);
static handler_t handler_ = NULL;
static void* handler_data_ = NULL;
void set_handler(handler_t h, void *d = NULL) {
handler_ = h;
handler_data = d;
}
void handle_event(int foo, void *bar) {
if (handler_ != NULL) handler_(foo, bar, handler_data_);
}
void foo_handler(int foo, void *bar, void *data) {
Foo *fooObj = static_cast<Foo*>(data);
fooObj->handler(foo, bar);
}
// in main
set_handler(foo_handler, &some_foo_object);