archimedes archimedes - 3 months ago 24
Swift Question

How to properly pass a callback-function from swift to c++?

I am trying to pass a callback-function from swift-code to c++ code. I am using the current version of Xcode. It works for simple variables, but not for functions so far:

cpp-class.cpp:

bool * swiftvar;

void register_var(bool * varpntr){
swiftvar = varpntr;
cout<<"registered"<<endl;
}

void switch_var(){
*swiftvar = !(*swiftvar);
cout<<"switched"<<endl;
}


cpp-class.hpp:

#ifdef __cplusplus
extern "C"{
#endif

void register_var(bool *);
void switch_var();

#ifdef __cplusplus
}
#endif


and in swift:

register_var(&testbool)
print(testbool)
switch_var()
print(testbool)


If i try the same for functions (which should be that simple in the current swift version as far as I know), I get errors. So how do I have to pass the function pointer in swift? All methods I found were causing errors. As i read, the old way of defining an UnsafeMutablePointer object an so on became obsolete, but how does it work now? I expect something like:

cpp-class.cpp:

void run_func(void * funcpntr()){
(*funcpntr)();
}


cpp-class.hpp:

void run_func(void *);


(swift-pseudo-code):

run_func(testfunc())


Or is there even a better solution to run swift-functions from wrapped cpp-code?

Any help would be really appreciated. Thanks in advance

Answer

First of all, you need to declare the function type properly in .cpp/.hpp .

.cpp:

void run_func(void (* funcpntr)()) {
    (*funcpntr)();
}

.hpp:

void run_func(void (* funcpntr)());

(You can omit the latter funcpntr as shown in Jarod42's answer. And this needs to be enclosed in extern "C" {...} as shown in the first "cpp-class.hpp:".)

And Swift side:

Function definition:

//This needs to be a toplevel function, which means it cannot be a method.
func test_func() {
    //...
}

To pass it to run_func():

    run_func(test_func)

Or you can pass a closure to run_func:

    //This closure cannot have captured variables.
    run_func {
        //...
    }