I'm writing a Node application (in TS) that needs to be interfaced with some native library.
I have a library (written in C) - let's consider it's a blackbox - and I'm writing a wrapper using NAN. The library native interface can be simplified into a following functions:
typedef void (*got_message_reply_cb)(context ctx, void * priv, struct X * the_reply);
context lib_connect();
bool lib_send_message(context ctx, message msg, got_message_reply_cb callback, void * priv);
I believe this is pretty straight-forward to understand.
So, I'm trying to wrap that black-box native library into something like:
class TheLibrary : public Nan::ObjectWrap {
Initialize(v8::Handle<v8::Object> target);
SendMessage(...)
}
And then to javascript object like:
class TheLibrary {
SendMessage(message: whatever, callback: (reply) => void); // or return promise, doesn't matter
}
How to do the actual handling of the callback in the NAN C++ module? I need to somehow pass the callback (represented probably by Local<Function> - which have, if I understand it correctly, limited scope) as a pointer to the function and then retrieve it back. How to do that? Thanks for your replies.
The high level answer is that you don't pass the JS callback function directly, but pass in a pointer to a function that somehow has your JS callback as a context value (in your example the priv parameter).
So for your case you write something like this:
void TheLibraryCallback(context ctx, void *instance, struct X *the_reply) {
((TheLibrary*)instance)->callback(ctx, the_reply);
}
In your TheLibrary you add a method void callback(context ctx, struct X * the_reply) that handles the callback. You call your library like this: lib_send_message(ctx, msg, TheLibraryCallback, this); with this being a TheLibrary instance.
So how do you call back the JS callback in your callback method? With nan you will have to make sure you are back in the main thread. There are examples out there, but I would suggest that you use the new N-API instead. The AsyncWorker helps with the boilerplate that you need to do to call the callback in the main thread.
Related
I am writing an audio rendering library that takes as input audio buffers, does some magic, then manage playback on a selected device. For this task, I decided to use Qt's QAudioOutput class.
I would like to allow the user to set callbacks when the state of the QAudioOutput object state changes (active, suspended, stopped and idle). I would connect these signals to a signal handler that would call the user-defined callbacks. However, I have the following restriction: no STL, no Qt, no Boost on the library header. I also need to stay compatible with C++98.
Right now, I have 2 solutions (with drawbacks) and I am looking to improve the design. My first solution was:
// library header
class AudioLibrary
{
typedef void ( *Callback )();
void setOnActiveCallback( Callback cb );
};
The problem with this solution is that the client can only pass static functions or non-capturing lambdas. This is too restrictive. Imagine a client who wants to do something as simple as re-enabling a button once playback finished. Not possible if the button is a member variable.
My second solution was that my interface would be an abstract class and contains pure virtual functions that would contain the desired behavior on state change. However, I am not sure this would be much fun for the client of the library...
Is there a cleaner and/or better solution that I ommited to think of?
This sounds like a C style callback.
class AudioLibrary
{
typedef void ( *Callback )( void * );
void setOnActiveCallback( Callback cb, void * context );
// Perhaps also include
template <typename Func>
void setOnActiveCallback( Func & f )
{
setOnActiveCallback( &Func::operator(), &f );
}
};
C-style callbacks without a means to pass context are completely utterly broken and your users will hate you for that. Don't do it. As soon as you have a intptr_t or void* typed context object, you can pass anything you wish to the callback, and quite efficiently at that. Yes, you can pass capturing lambdas, member methods, etc.
E.g.:
class AudioLibrary {
typedef void (*Callback)(void*);
void setOnActiveCallback(Callback cb, void * context);
};
Then:
static void functionCallback(void * context) {
auto f = reinterpret_cast<std::function<void()>*>(context);
f();
}
struct User {
AudoLibrary * m_audio;
std::function<void()> f_onActive{std::bind(&User::onActive, this)};
void onActive();
User(AudioLibrary * audio) : m_audio(audio) {
audio->setOnActiveCallback(functionCallback, &f_member);
}
};
I need to call a C++ method and pass in a callback method as a parameter... from ObjectiveC method...
This callback method would then be triggered multiple times in ObjectiveC... as it's a callback... and so then I need to trap that ObjectiveC callback method back as it will be called as a closure from Swift code...
This is the C++ Method Signature
static bool cPlusPlusMethodWithCallBack(const std::string& someText, void (*someCallback)(unsigned int) = NULL, unsigned int someNum = 0);
My Question is what should be the Block syntax of this Callback Method declared in ObjectiveC (in .mm and .h) which can then be passed as a parameter to this someCallback in C++
I am a Swift developer so bit stuck on ObjectiveC... Many Thanks
You can't pass an Objective-C block (or a Swift closure) as a function pointer argument like that. You'll need to create a separate, standalone function, and pass that in as the callback.
void MyCallback(unsigned int value)
{
// ...do something...
}
And in your main code:
cPlusPlusMethodWithCallBack("something", MyCallback);
Now, the downside of this is that in your callback, you'll often need to reference a particular Objective-C object in order to properly handle the callback. If that's something you need with this particular callback, you'll need to save it off somewhere as a static variable so that it can be accessed from the MyCallback function.
Alternatively, if you have control over the cPlusPlusMethodWithCallBack source code, you can update it to take a void * "reference" parameter, and then supply that parameter as an argument when you call the callback:
static void cPlusPlusMethodWithCallback(void (*callback)(void *ref), void *ref)
{
// ...really time consuming processing...
callback(ref);
}
Then, update your callback function:
void MyCallback(void *ref)
{
ObjectiveCObject *obj = (ObjectiveCObject *)ref;
[obj doSomething];
}
And when you initially call the method, just pass in the object you need as the reference parameter:
cPlusPlusMethodWithCallback(MyCallback, myObjectiveCObject);
I'm writing a C++ programm using GTK+3.0. Anyway, I think this question may apply to any framework that uses events / signals.
I have a container class, say containerClass and a child class, say childClass. A childClass object child is contained inside a containerClass object container.
The child object is written to modify properties of something. To this aim, it has GtkEntry, GtkButton and so on. When I click the "save button", an event is raised.
This event must be handled by the container object, because the container is interfaced with a database in someway.
Hereafter, you find the solution I'm using to do the job:
// Child class
class childClass {
void setClickHandler_External(void (*extFun)(string property), void *);
void (*clickHandler_External)(string, void *);
void *clickHandler_External_Data;
static void buttonClicked(GtkWidget *widget, void *data);
}
void childClass::setClickHandler_External(void (*extFun)(string), void *data) {
// Set the external event handler
clickHandler_External = extFun;
clickHandler_External_Data = data;
}
void childClass::buttonClicked(GtkWidget *widget, void *data) {
childClass *m = (childClass *)data;
// Call the external event handler
m->clickHandler_External(property, m->clickHandler_External_Data);
}
// Container Class
class containerClass {
childClass child;
static void clickHandler(string property, void *data);
}
containerClass::containerClass() {
// Set the event handler
child.setClickHandler_External((void(*)(string))&(this->clickHandler), (void *)this);
}
void containerClass::clickHandler(string property, void *data) {
// Event handler in the upper class
containerClass *m = (containerClass *)data;
//FINALLY, DO THE JOB WITH PROPERTY!!!
}
This works well and does the job. Anyway, I was wondering if there is a smarter and cleaner way to achieve the same aim, maybe without using pointers to static functions, or by defining some kind of pattern to be reused everytime I need to have the same mechanism.
Thanks in advance
Gtkmm uses the sigc++ library to take care of all of this for you. There is no need to write it yourself.
Documentation links:
Signals overview
Appendix with detailed information
So, in this case, I would use something like
button.signal_clicked().connect(sigc::mem_fun(container, &containerClass::clickHandler));
while making sure that containerClass::clickHander has the appropriate number of arguments.
My first suggestion would be to use use templates to improve the type safety of what you are doing:
template< class ParamType >
void childClass::setClickHandler_External(void (*extFun)(string, ParamType *),
ParamType *data)
{
// Set the external event handler
clickHandler_External = (void ()(string,void*))extFun;
clickHandler_External_Data = (void*)data;
}
Then you can simplify the containerClass implementation as such:
// Container Class
class containerClass {
childClass child;
static void clickHandler(string property, containerClass *data);
}
containerClass::containerClass() {
// Set the event handler
child.setClickHandler_External(&containerClass::clickHandler, this);
}
void containerClass::clickHandler(string property, containerClass *data) {
//FINALLY, DO THE JOB WITH PROPERTY!!!
}
While it's great that this cleans up the implementation, removing the explicit casting from all the container implementors, that's not really the point. The point is to prevent you from passing wrong pointers into setClickHandler_External, causing crashes on the back end when events get dispatched.
My next step would take us further from your implementation, but would require more details about what you are actually doing. Depending on your needs that would be looking into:
Inheritance: should containerClass derive from childClass? That would provide access to a virtual function table that we could override.
Functors: look at boost::function and boost::bind to implement functors, eliminating the intermediate static function call.
Lambda Functions: bleeding edge (C++11 or later), but may be a good fit for this kind of forwarding function.
I have a game I am integrating with Lua scripting in order to allow customization.
I am using a C++ Lua wrapper:
https://github.com/tomaka/luawrapper
In my Lua script I am calling something like this:
function sprite_factory()
local sprite = sprite_new() -- register_new_sprite(name)
sprite:RegisterCallback("on_activate", function ()
sprite:SetState("closed")
end)
end
In my C++ code I have built a Sprite class and I'm using registerFunction to make the member methods available to Lua e.g. RegisterCallback is called on the sprite object returned by sprite_new()
bool RegisterCallback(const std::string hook, const std::function<void()> callback) {
callback();
mCallback = callback;
return true;
}
If I do the callback inside the RegisterCallback method, it works fine. However, I want to store the callback to be used as a raised event.
When I call this method later in my code:
void DoCallback() {
mCallback(); //raises exception
}
I get an exception:
libc++abi.dylib: terminating with uncaught exception of type
std::__1::bad_function_call: std::exception
I am declaring mCallback as a private:
std::function<void()> mCallback = NULL;
I'm not sure what is going on here.
I would suspect that there is an issue with the way mCallback is declared.
I am passing a callback function to a library. What the callback essentially does is receive updates from the dll and send it to GUI to display. The problem is that since the callback is global or static function, it doesn't know about the GUI and who to pass which in my case will be dialog. The approach I have used to accomplish this is to use singleton and a proxy (sort of).
class CDispatcher
{
public:
CDispatcher(void);
~CDispatcher(void);
protected:
static HWND m_hWnd;
public:
static void SetWindow( HWND hWnd );
static void Dispatch(int code, char * msg);
};
Later in the code
BOOL CTestDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// I need to set this before I set callback
CDispatcher::SetWindow( m_hWnd );
//now I can set the callback
LibRegisterCallback( CDispatcher::Dispatch );
return TRUE; // return TRUE unless you set the focus to a control
}
While this works but first I don't know if my CDispatcher class is good module. It doesn't seem like a good singleton neither it looks like a good proxy. Maybe I could pass the handle of the window in constructor which would make it better but I don't if that's even possible since I am never instantiating the singleton. Another thing is I never how to instantiate CDispatcher because again its just a all global members.
Is this a case where proxy design pattern can be applied in a better way (I am guessing in conjuction with singleton)? Maybe another pattern solves this problem more elegantly? Or is my implementation fine?