First, callback_t
is not an identifier. I don't see it typedef
anywhere..
Second, you need some way of telling C++ that the callback is your swift function. To do that, I pass it as a parameter to the C++ function similar to how we do it in Objective-C and Swift.. Otherwise you need to store the callback in a global variable somewhere and have C++ access it.
Using the first method of passing the callback as a parameter:
First in the C++ header (Foo.h
) I did (Do NOT remove the ifdef
stuff.. the compiler uses C linkage when importing to Swift but when compiling the C++ side, it'll be mangled so to make it use C linkage, we extern "C"
the code):
#ifndef Foo_hpp
#define Foo_hpp
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef void(*callback_t)(const char *);
void callback_web_disconnected(callback_t);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* Foo_hpp */
Then in the implementation file (Foo.cpp
) I did:
#include "Foo.h"
#include <thread>
#include <iostream>
#ifdef __cplusplus
extern "C" {
#endif
void callback_web_disconnected(callback_t callback)
{
std::thread t = std::thread([callback] {
std::this_thread::sleep_for(std::chrono::seconds(2));
if (callback)
{
callback("Hello World");
}
});
t.detach();
}
#ifdef __cplusplus
} // extern "C"
#endif
Then in ViewController.swift I did:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
callback_web_disconnected({
if let ptr = $0 {
let str = String(cString: ptr)
print(str)
}
})
}
}
It works fine. The Swift code gets called from C++ after 2 seconds has passed.
Using the second method of storing the callback in a global variable (which I despise but let's not get into that)..
In Foo.h
I did:
#ifndef Foo_hpp
#define Foo_hpp
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef void(*callback_t)(const char *);
callback_t globalCallback; //Declare a global variable..
void callback_web_disconnected();
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* Foo_hpp */
In Foo.cpp
I did:
#include "Foo.h"
#include <thread>
#include <iostream>
#ifdef __cplusplus
extern "C" {
#endif
void callback_web_disconnected()
{
std::thread t = std::thread([] {
std::this_thread::sleep_for(std::chrono::seconds(2));
if (globalCallback)
{
globalCallback("Hello World");
}
});
t.detach();
}
#ifdef __cplusplus
} // extern "C"
#endif
In ViewController.swift
, I did:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//Set the globalCallback variable to some block or function we want to be called..
globalCallback = {
if let ptr = $0 {
let str = String(cString: ptr)
print(str)
}
}
//Trigger our test.. I guess your C++ code will be doing this anyway and it'll call the globalCallback.. but for the sake of this example, I've done it here..
callback_web_disconnected()
}
}