Convert C++ function pointer to c function pointer - c++

I am developing a C++ application using a C library. I have to send a pointer to function to the C library.
This is my class:
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private:
Ui::MainWindow *ui;
void f(int*);
private slots:
void on_btn_clicked();
};
This is my on_btn_clicked function:
void MainWindow::on_btn_clicked()
{
void (MainWindow::* ptfptr) (int*) = &MainWindow::f;
c_library_function(static_cast<void()(int*)>(ptfptr), NULL);
}
The C function should get a pointer to a such function : void f(int*).
But the code above doesn't work, I cannot succeed to convert my f member function to the desired pointer.
Can anybody please help?

You can't pass a non-static member function pointer as an ordinary function pointer. They're not the same thing, and probably not even the same size.
You can however (usually) pass a pointer to a static member function through C. Usually when registering a callback in a C API, you also get to pass a "user data" pointer which gets passed back to your registered function. So you can do something like:
class MyClass
{
void non_static_func(/* args */);
public:
static void static_func(MyClass *ptr, /* other args */) {
ptr->non_static_func(/* other args */);
}
};
Then register your callback as
c_library_function(MyClass::static_func, this);
i.e. pass the instance pointer to the static method, and use that as a forwarding function.
Strictly speaking for total portability you need to use a free function declared extern "C" rather than a static member to do your forwarding (declared as a friend if necessary), but practically speaking I've never had any problems using this method to interface C++ code with GObject code, which is C callback-heavy.

You can't pass a function pointer to a non-static member function. What you can do is to create a static or global function that makes the call with an instance parameter.
Here's an example I find useful which uses a helper class with two members: a function wrapper and a callback function that calls the wrapper.
template <typename T>
struct Callback;
template <typename Ret, typename... Params>
struct Callback<Ret(Params...)> {
template <typename... Args>
static Ret callback(Args... args) { return func(args...); }
static std::function<Ret(Params...)> func;
};
// Initialize the static member.
template <typename Ret, typename... Params>
std::function<Ret(Params...)> Callback<Ret(Params...)>::func;
Using this you can store any callable, even non-static member functions (using std::bind) and convert to a c-pointer using the Callback::callback function. E.g:
struct Foo {
void print(int* x) { // Some member function.
std::cout << *x << std::endl;
}
};
int main() {
Foo foo; // Create instance of Foo.
// Store member function and the instance using std::bind.
Callback<void(int*)>::func = std::bind(&Foo::print, foo, std::placeholders::_1);
// Convert callback-function to c-pointer.
void (*c_func)(int*) = static_cast<decltype(c_func)>(Callback<void(int*)>::callback);
// Use in any way you wish.
std::unique_ptr<int> iptr{new int(5)};
c_func(iptr.get());
}

If I recall it correctly, Only static methods of a class can be accessed via "normal" C pointer to function syntax. So try to make it static. The pointer to a method of a class needs extra information, such as the "object" (this) which has no meaning for a pure C method.
The FAQ shown here has good explanation and a possible (ugly) solution for your problem.

#Snps answer is great. I extended it with a maker function that creates a callback, as I always use void callbacks without parameters:
typedef void (*voidCCallback)();
template<typename T>
voidCCallback makeCCallback(void (T::*method)(),T* r){
Callback<void()>::func = std::bind(method, r);
void (*c_function_pointer)() = static_cast<decltype(c_function_pointer)>(Callback<void()>::callback);
return c_function_pointer;
}
From then on, you can create your plain C callback from within the class or anywhere else and have the member called:
voidCCallback callback = makeCCallback(&Foo::print, this);
plainOldCFunction(callback);

#Snps answer is perfect! But as #DXM mentioned it can hold only one callback. I've improved it a little, now it can keep many callbacks of the same type. It's a little bit strange, but works perfect:
#include <type_traits>
template<typename T>
struct ActualType {
typedef T type;
};
template<typename T>
struct ActualType<T*> {
typedef typename ActualType<T>::type type;
};
template<typename T, unsigned int n,typename CallerType>
struct Callback;
template<typename Ret, typename ... Params, unsigned int n,typename CallerType>
struct Callback<Ret(Params...), n,CallerType> {
typedef Ret (*ret_cb)(Params...);
template<typename ... Args>
static Ret callback(Args ... args) {
func(args...);
}
static ret_cb getCallback(std::function<Ret(Params...)> fn) {
func = fn;
return static_cast<ret_cb>(Callback<Ret(Params...), n,CallerType>::callback);
}
static std::function<Ret(Params...)> func;
};
template<typename Ret, typename ... Params, unsigned int n,typename CallerType>
std::function<Ret(Params...)> Callback<Ret(Params...), n,CallerType>::func;
#define GETCB(ptrtype,callertype) Callback<ActualType<ptrtype>::type,__COUNTER__,callertype>::getCallback
Now you can just do something like this:
typedef void (cb_type)(uint8_t, uint8_t);
class testfunc {
public:
void test(int x) {
std::cout << "in testfunc.test " <<x<< std::endl;
}
void test1(int x) {
std::cout << "in testfunc.test1 " <<x<< std::endl;
}
};
cb_type* f = GETCB(cb_type, testfunc)(std::bind(&testfunc::test, tf, std::placeholders::_2));
cb_type* f1 = GETCB(cb_type, testfunc)(
std::bind(&testfunc::test1, tf, std::placeholders::_2));
f(5, 4);
f1(5, 7);

The short answer is: you can convert a member function pointer to an ordinary C function pointer using std::mem_fn.
That is the answer to the question as given, but this question seems to have a confused premise, as the asker expects C code to be able to call an instance method of MainWindow without having a MainWindow*, which is simply impossible.
If you use mem_fn to cast MainWindow::on_btn_clicked to a C function pointer, then you still a function that takes a MainWindow* as its first argument.
void (*window_callback)(MainWindow*,int*) = std::mem_fn(&MainWindow::on_btn_clicked);
That is the answer to the question as given, but it doesn't match the interface. You would have to write a C function to wrap the call to a specific instance (after all, your C API code knows nothing about MainWindow or any specific instance of it):
void window_button_click_wrapper(int* arg)
{
MainWindow::inst()->on_btn_clicked(arg);
}
This is considered an OO anti-pattern, but since the C API knows nothing about your object, it's the only way.

I've got an idea (not entirely standard-compliant, as extern "C" is missing):
class MainWindow;
static MainWindow* instance;
class MainWindow
{
public:
MainWindow()
{
instance = this;
registerCallback([](int* arg){instance->...});
}
};
You will have problems if multiple instances of MainWindow are instantiated.

Related

Invoking a method from stored class reference

I am working on a callback template class where the callback isn't function or functor but a class reference. Depending on the context, the callback is invoked by calling specific method from registered class, roughly implemented as follows:
template<typename T>
class callback
{
public:
// ctors, moves, copies, assignments, ...
template<typename F, typename ... A>
void invoke(F method_ptr, A ... args)
{
(*m_interface_ptr.*method_ptr)(std::forward<A>(args) ...);
}
private:
T * m_interface_ptr;
};
Now, the usage of such template looks something like this:
struct intf
{
virtual void method_a() { ... }
virtual void method_b(int n) { ... }
};
intf i;
callback<intf> c;
c.subscribe(i);
c.invoke(&intf::method_a);
c.invoke(&intf::method_b, 7);
This code works just fine, but the part where I am calling a method from class reference feels a bit odd. Trouble comes if I try to extend the callback class to support both class reference callbacks and functor or plain function callbacks.
Is there a standard way of storing the class reference and invoking methods on it? Something like std::function but supporting my case.
Usecase #1: Calling a method from stored class reference
intf i;
// Create some std:: reference wrapper which allows custom method calls by name
std::some_ref_callable ri(i);
// Pass into callback and invoke
callback<std::some_callable<intf>> ci(ri);
ci.invoke(&intf::method_b, 7);
Usecase #2: Calling a lambda
auto l = []{ /* generic lambda */ };
callback<decltype(l)> cf(l);
cf.invoke();
Usecase #3: Calling a plain function
void func(int n){ /* plain function with param */ }
callback<decltype(func)> cf(func);
cf.invoke(1337);
Possible custom implementation would look something like this:
template<typename T>
struct some_ref_callable
{
template<typename R, typename ... A>
auto operator ()(R(T:: * method_ptr)(A ...), A ... args)
{
return (*m_object_ptr.*method_ptr)(std::forward<A>(args) ...);
}
T * m_object_ptr = nullptr;
};

How To Set Class Method in sigaction sa_sigaction?

I have a class and I want to set the class method as an argument of sigaction because I need to use some class attributes:
class MyClass {
void action(int sn, siginfo_t* t, void* ctx) {
...
}
};
int main() {
MyClass c;
struct sigaction sig_action;
sig_action.sa_sigaction = c.action; // ERROR!
}
Even I've tried to use std::bind with reinterpret_cast but didn't work.
So, how can I set sa_sigaction a class method?
NOTE: it SHOULD be a class method and not a static method or a function.
If you take a look at declaration of sigaction::sa_sigaction, you'll find that it is void (*)(int,siginfo_t*,void*). This is a pointer to function.
NOTE: it SHOULD be a class method and not a static method or a function.
It cannot be, because pointers to functions can not point to non-static member functions. You must pass a pointer to a non-member or a static member function as the signal handler. That function may in turn call the non-static member function if you so desire (as long as the function is async signal safe).
I need to use some class attributes
Make sure that those attributes are of type volatile sig_atomic_t.
class MyClass {
void action(int sn, siginfo_t* t, void* ctx) {
...
}
};
MyClass c;
void action(int sn, siginfo_t* t, void* ctx) {
c.action(sn, t, ctx);
}
int main() {
struct sigaction sig_action;
sig_action.sa_sigaction = action;
}

Give another class access to specific methods

I am working on game engine as a project during the summer. Every scriptable component should have access to some methods in the scene which they are in. To make this possible i pass lambdas from the scene that calls the respective methods to the scriptable where they are implicitly converted to std::function types.
Scene.h:
class Scene
{
private:
unsigned int _currentId;
std::vector<System*> _systems;
//SCRIPTABLE NEEDS THE BELOW METHODS THESE EXCLUSIVELY:
bool exists(unsigned id);
void destroy(unsigned int);
void addComponent(Component*, unsigned int);
template<typename T> T& getComponent(unsigned int);
template<typename T> bool hasComponent(unsigned int);
template<typename T> void removeComponent(unsigned int);
protected:
unsigned int instantiate(std::vector<Component*>);
public:
Scene(ChangeSceneCallback);
~Scene();
void initiate();
void update(long dt);
};
template<typename T>
inline T & Scene::getComponent(unsigned int id)
{
for (System* system : _systems) {
if (system->corresponds(T)) {
return static_cast<T*>(system->getComponent(entityId));
}
}
}
template<typename T>
inline bool Scene::hasComponent(unsigned int id)
{
for (System* system : _systems) {
if (system->corresponds(T)) {
return system->contains(id);
}
}
}
template<typename T>
inline void Scene::removeComponent(unsigned int id)
{
for (System* system : _systems) {
if (system->corresponds(T)) {
return system->destroy(id);
}
}
}
The callback method works for the non-template functions i need access to, but not the templated ones, so it's out of the question.
Scriptable:
typedef std::function<void(int)> ChangeSceneCallback;
typedef std::function<int(std::vector<Component*>)> InstantiateCallback;
typedef std::function<void(int)> DestroyCallback;
typedef std::function<bool(int)> ExistCallback;
typedef std::function<void(Component*, unsigned int)> AddComponentCallback;
class Scriptable: public Component
{
protected:
ChangeSceneCallback changeScene;
InstantiateCallback instantiate;
DestroyCallback destroy;
ExistCallback exists;
public:
~Scriptable();
Scriptable();
void assignCallbacks(ChangeSceneCallback, InstantiateCallback etc ...);
virtual void init() = 0;
virtual void update() = 0;
};
Scriptable can't have access to public methods in scene because this would give the user / developer access to them (Scriptable is a base class for the behaviour of the game). That is why i need to come up with something that gives scriptable limited access to scene.
Any thoughts?
You cannot have a type erased "template callback". You have to choose between the template or the type erasure. Let me explain.
This is what a "template callback" look like. This is in fact a generic lambda:
auto print_callback = [](auto var) {
std::cout << var << std::endl;
}
print_callback(4) ; // prints "4"
print_callback(4.5); // prints "4.5"
print_callback("hello"); // prints "hello"
It seems good but notice that you can't do that with std::function, since you have to predefine the signature.
std::function<void(int)> func_print_callback = print_callback;
func_print_callback(5); // Yay! Prints "5"
func_print_callback("hello"); // error
The thing is, you might think the limitation is only because std::function need a specific signature to work with, but the limitation is much deeper than that.
The thing is, the is no template function. They don't exists. Function template on the other hand, do exist. Why I emphasize so much on the order of my words is because the name of this thing says it all: it is not a function, it a template that is used to make functions.
Here's a simple example:
template<typename T>
void foo(T t) {
std::cout << t << std::endl;
}
This function is not compiled. Because it's not a function. No function foo will exist until the hole T has been filled.
How do you fill the hole named T supposed to be a type?
By filling it with a type of course!
foo(5.4); // the hole T is `double`
When the compiler sees this, it knows you need a function named foo that takes a double as parameter. There is no function named foo that takes a double. But we gave the compiler a tool to create one: the template!
So the compiler will generate this function:
void foo_double(double t) {
std::cout << t std::endl;
}
The word here is this: generate. The compiler need to create the function in order to exist. The compiler generate code for you.
When the function is generated and compiled, T do not exist anymore. A template parameter is a compile-time entity, and only the compiler knows about them.
Now, I'll explain to you why there is no such thing as a template callback.
Type erased container such as std::function are implemented with pointer to function. I'll use type aliases to ease the syntax a bit. It works like this:
// A function
void foo(int) {}
// The type of the pointer to function
using func_ptr = void(*)(int);
// A pointer to foo
func_ptr ptr = &foo;
The pointer to the function foo has a value that points to the location of foo in the memory.
Now imagine we have a way to have template function pointer. We would have to point to a function that does not exist yet. It has no memory location, so it cannot make sense. And through the pointer, when invoked as a function, you'd have to generate the function code.
Since a pointer to function can point to any function, even functions that aren't known to the compiler yet, you'd have to somehow generate the function code and compile it. But the value of the pointer, to which function our pointer points to, is defined at runtime! So you'd have to compile code at runtime, for code that you don't know yet, from a value that does not exist, when the compiler don't exist anymore. As you can see, pointer to template function, template std::function or virtual template function cannot exist.
Now that you have understood the problem, let me propose a solution: drop the callback usage. You should call those functions directly.
You seem to use callback only to be able to call private member functions. This is the wrong way to do it, even if it works. What you need is friend, the feature of C++ that allows you to access private members.
class Scene {
friend Component;
// ...
};
class Component {
protected:
// Let `scene` be a reference to your scene
void addComponent(Component* c, unsigned int id) {
scene.addComponent(c, id);
}
template<typename T>
T& getComponent(unsigned int id) {
return scene.getComponent<T>(id);
}
template<typename T>
bool hasComponent(unsigned int id) {
return scene.hasComponent(id);
}
template<typename T>
void removeComponent(unsigned int id) {
removeComponent(id);
}
// ...
};
Since the Component class is the only friend to Scene, only it can call private member functions. Since all those newly defined functions in Component are protected, only class that extends from Component can call those. They are invoked like this:
class Scriptable : public Component {
void foo() {
hasComponent<Bar>(87); // works, call function defined in `Component`
}
};

How to pass a method as callback to another class?

I have a question regarding callbacks using tr1::function. I've defined the following:
class SomeClass {
public:
typedef std::tr1::function<void(unsigned char*, int)> Callback;
void registerCallback(Callback);
private:
Callback callback;
}
I've defined another class:
class SomeOtherClass {
void myCallback(unsigned char*, int);
}
Now I want to register my function 'myCallback' as callback at class 'SomeClass'using the method 'registerCallback'. However, it is not working. I've had a look on the boost documentation on the function and it seems legit to use (member) methods of a class for callbacks. Am I wrong?
Thanks in advance!
Member functions have an implicit first parameter, a this pointer so as to know which object to call the function on. Normally, it's hidden from you, but to bind a member function to std::function, you need to explicitly provide the class type in template parameter.
#include <functional>
#include <iostream>
struct Callback_t {
void myCallback(int)
{
std::cout << "You called me?";
}
};
class SomeClass {
public:
SomeClass() : callback() { }
typedef std::function<void(Callback_t*, int)> Callback;
// ^^^^^^^^^^^
void registerCallback(const Callback& c)
{
callback = c;
}
void callOn(Callback_t* p)
{
callback(p, 42);
}
private:
Callback callback;
};
int main()
{
SomeClass sc;
sc.registerCallback(&Callback_t::myCallback);
Callback_t cb; // we need an instance of Callback_t to call a member on
sc.callOn(&cb);
}
Output: You called me?;
Why all this complicated mumbo-jumbo?
Why not create a class as thus (for example)
Class MouseOverEventCallBack
{
public:
virtual void RunMouseOverCallback() = 0;
};
Then just create classes that inherit this class (and redefine the method RunMouseOverCallback)
Then Register function just needs to be
void registerCallback(MouseOverEventCallBack *callbackObject); // possible could use a reference
The register method will just call the method and the object will have all that it needs.
Seems a bit simpler. Let the compiler do the work with pointers to functions etc.
the function void (*)(unsigned char*, int) is a free function, which is a different type from void (SomeOtherClass::*)(unsigned char*, int), thus the error. You need an object to call the latter, while the former is a free function.
Look at the possible solutions listed in the Boost documentation
Another possibility is that your SomeOtherClass::myCallback is private, so you do not have access to it.
Use templates:
template <class T>
class B
{
public:
typedef void (T::*TCallBackFunction)(void);
void SetCallBack(T* pCallBackClass, TCallBackFunction pCallBackFunction)
{
if(pCallBackFunction && pCallBackClass)
{
m_pCallBackFunction = pCallBackFunction;
m_pCallBackClass = pCallBackClass;
}
}
void StartCallBackFunction()
{
(pCallBackClass->(*m_pCallBackFunction))();
}
private:
TCallBackFunction m_pCallBackFunction;
T* m_pCallBackClass;
};
Such like this. And use it:
...
B<MyClass> b;
b.SetCallBack(&b, &MyClass::MyFunction);
...

C++ member function applied to object

I want to call member function by passing it as template parameter, without using boost is possible. Here is an example off what I tried to do,
class object { void method(); }
{
object object_instance;
...
apply<object:: method>();
...
template<class F>
void apply() { F(object_instance); } // want to call object_instance.F()
}
that does not work, so question is how do I go about binding object method to an object.
Thanks
above is an example, not the real code. I have a bunch of functions differing only in name, but with many parameters, that I want to wrap around in operators.
Something like:
struct foo
{
void bar(void) {}
};
template <typename R, typename C>
R apply(C& pObject, R (C::*pFunc)())
{
return (pObject.*pFunc)();
}
int main(void)
{
foo f;
apply(f, &foo::bar);
}
this.
This is similar to your code, and will allow passing a member function as a template parameter:
class object { public: void method() {} };
object object_instance;
template<void (object::*F)()>
void apply() {
(object_instance.*F)();
}
int main() {
apply<&object::method>();
return 0;
}
As a member function isn't a type or integral value, you can't pass it as a template parameter. You could do what you seem to want by creating a struct which calls the member function, though having object_instance in scope in the template is rather smelly.
What are you actually trying to do?
This example is for rvalue references in c++ox. Does not work on all compilers.
class Sample
{
public:
void fun() { cout << "Sample::fun\n"; }
};
template<typename Function>
void FunCall( Function&& f)
{
f();
}
void RvaluesDemo()
{
FunCall([&]
{
Sample().fun();
});
}