Combining function, bind, c++ and managed code - c++

I have a c++ function which is expecting a function object (AuthenticateNotifyFunc) to be passed to it thus:
class lc_Authenticate
{
public:
typedef enum {
kAbort,
kContinue
} lc_AuthenticateStatus;
typedef std::tr1::function<lc_AuthenticateStatus (const string &msg)> AuthenticateNotifyFunc;
bool Authenticate(lc_AuthenticateParams &params,
AuthenticateNotifyFunc notifyFunc);
}
Within a managed c++ project, I am attempting to define a parameter to pass to the above function thus:
public ref class Form1 : public System::Windows::Forms::Form
{
public:
lc_Authenticate::lc_AuthenticateStatus UpdateStatus(const string &msg)
{
<<DO SOMETHING>>
return(lc_Authenticate::kContinue);
}
void test()
{
string appKey, appSecret;
appKey = GetString(this->appKeyTextBox->Text);
appSecret = GetString(this->appSecretTextBox->Text);
lc_Authenticate dbauth;
lc_AuthenticateParams params(appKey, appSecret);
// DOESN'T COMPILE won't let me take address of member function
// or know about _1
lc_Authenticate::AuthenticateNotifyFunc func =
std::tr1::bind(&Form1::UpdateStatus, this, _1);
dbauth.Authenticate(params, func);
}
};
So I am trying to implement a generic method of passing a function to a c++ method in such a way that it doesn't care whether the passed function is static or a member function. And I'm not clear how do do this from managed code.

You cannot bind to an instance method of a managed class by design. The garbage collector moves the object around when compacting the heap, causing this to change. You'll need to use a managed delegate. So you can't avoid a native helper class that provides the stable callback you need for your function<>. You can get back to managed code from there with Marshal::GetFunctionPointerForDelegate().

Related

Initializing a new nested class from outer class function

I'm currently learning nested classes in C++ while building a project and I currently inside setupBLE() I need to pass one of the nested classes but to init that new class I need to pass to its constructor the outer class so it can access its variables and functions but I'm not exactly sure how to pass to the constructor the pointer of the class that's trying to create it.
It's a bit confusing so I hope the code helps with it.
Like in python we have self but in C++ as far as I know we don't have that so I was wondering what should I pass to the constructor.
Code (PillDispenser.h):
class PillDispenser {
public:
explicit PillDispenser(BLEAddress deviceAddress);
private:
BLEAddress _device_address;
BLEAdvertisedDevice _device;
bool _connected;
// Device properties
std::string _device_name;
// Callbacks
static void notifyCallBack();
class AdvertisedDeviceCallBack : public BLEAdvertisedDeviceCallbacks {
PillDispenser &_outer;
explicit AdvertisedDeviceCallBack(PillDispenser &outer) : _outer(outer){};
void onResult(BLEAdvertisedDevice advertisedDevice) override;
};
}
Code (PillDispenser.cpp):
void PillDispenser::setupBLE() {
BLEScan *scanner = BLEDevice::getScan();
scanner->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCallBack());
scanner->setInterval(SCAN_INTERVAL);
scanner->setWindow(SCAN_WINDOW);
scanner->setActiveScan(true);
scanner->start(SCAN_DURATION);
}
Issue:
This line is trying to use the default constructor which does not exist
scanner->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCallBack());
instead you should use the explicit constructor you defined
scanner->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCallBack(*this));
note that this (in this context) has type PillDispenser* so you have to dereference with * to get a PillDispenser&

Cast error passing a void function with namespace

I'm trying to wrap, in a C++ class, a server that I wrote using mongoose (a C library). The problem is that I'm trying to pass the function ev_handler to the mg_create_server(), which create the instance of the server in mongoose. But it gives a casting error I believe:
src/Server.cpp:16:44: error: cannot convert 'Server::ev_handler' from
type 'int (Server::)(mg_connection*, mg_event)' to type 'mg_handler_t
{aka int (*)(mg_connection*, mg_event)}' server =
mg_create_server(NULL, ev_handler);
I tried to make ev_handler static but it has send_index_page(conn) that has to be inside the wrapper class.
void Server::start() {
struct mg_server *server;
int numberOfObjects;
_application = new Application();
_application->start();
// Create and configure the server
server = mg_create_server(NULL, ev_handler);
//... more code here ...
}
int Server::ev_handler(struct mg_connection *conn, enum mg_event ev) {
switch (ev) {
case MG_AUTH: return MG_TRUE;
case MG_REQUEST: return send_index_page(conn);
default: return MG_FALSE;
}
}
Your problem is that you're passing a C++ member function to parameter that wants a free function pointer.
Mongoose is a C API and all of its callback parameters are C style functions, which in C++ are free (not member) functions.
A member function pointer is different from a free function pointer in that it needs the this , or the object on which the method is being called, in order to be called.
In your case, you are passing a member function pointer on the Server class.
When interacting which C APIs, it's common to pass a void* context object which is then passed to the callback. You then pass a pointer to a free function or a static class method (which has no this and can therefore work with C APIs). When the callback is invoked, you then cast the context object to the correct type and call a member function to get back into the object context. I can't see any such facility in Mongoose. Maybe it's there and I'm just not finding it.
You may want to try the already exising Mongoose C++ which forks the original Mongoose project to work better with C++: https://github.com/Gregwar/mongoose-cpp
The callback needs to be static, then you should use a static stub to redirect to the class instance.
Storing the instance of your class in server_param attribute of mg_server will allow to get it back in a static stub and forward it to this instance.
This could be achieve like this :
class Server
{
public:
void start() {
mg_create_server(this, ev_handlerStub);
}
static int ev_handlerStub(struct mg_connection *conn, enum mg_event ev) {
((Server*)conn->server_param)->ev_handler(conn, ev);
}
int ev_handler(struct mg_connection *conn, enum mg_event ev) {
// job to do with the class instance
}
};
Proceeding like this, allow access to class instance inside its ev_handler method.

member function pointer - how to do this?

I have the following:
class NetRequest: public QObject {
Q_OBJECT
public:
NetRequest(QString postData, void(BrowserApp::*f)(QByteArray));
QString postData;
void (BrowserApp::*fn)(QByteArray);
public slots:
void requestFinished(QNetworkReply *r);
}
and the cpp is:
NetRequest::NetRequest(QString postData, void(BrowserApp::*f)(QByteArray)) {
this->postData = postData;
this->fn = f;
}
void NetRequest::requestFinished(QNetworkReply *r) {
QByteArray data;
fn(data);<--- this doesn't work
}
I am trying to call the function "fn" in requestFinished but the compiler doesn't let me - what am I please doing wrong?
Thank you for all your help!
When you have a pointer-to-member-function, in order to call through it you must also have a pointer to the object you are using for the call.
But your code:
fn(data);
Has no such object pointer. You probably are assuming that an object is associated with the member function pointer -- but it isn't.
Try this:
(that->*fn)(data);
that is a pointer to a BrowserApp object. It will need to be either passed in to the requestFinished function, or somehow stored in the NetRequest object -- probably at the same time when fn is set.
I suggest you look into std::function and std::bind. They will help you in many ways when it comes to "function pointers".
Then it would look something like this instead:
class NetRequest: public QObject {
std::function<void(QByteArray)> fn;
// ...
public:
NetRequest::NetRequest(QString postData, std::function<void(QByteArray)> f) {
// ...
fn = f;
}
// ...
};
Now when creating an instance of the NetRequest object, you must use std::bind to bind a function from the BrowserApp class to the std::function object:
BrowserApp app;
NetRequest request("some string", std::bind(&BrowserApp::SomeFunction, app));
The nice thing about using std::function is that the callback function no longer have to be a BrowserApp member function, it can by any function, including lambda expressions.

boost member function pointers

I am very new to the boost libraries.
I was trying to accomplish something for a graphical program, by binding the callbacks passed
to glutDisplayFunc(), etc to a single class.
I wanted to accomplish this without having some constant global class object.
To explain in code:
class CallbackHolder {
public:
void dostuff(void) {
// etc.
}
};
void bind() {
glutIdleFunc((new CallbackHolder())->dostuff);
}
I know this is possible through the usage of boost::bind and boost::function.
One issue I did see however was converting the boost::function back to a normal function pointer.
How would you accomplish this?
You can't convert from boost::function to a normal function pointer, and you can't convert from a member function pointer to a normal function pointer. There are workarounds for functions accepting callback where you can provide user data.
Unfortunately the glut interface doesn't let you provide user data. This means you're stuck with the ugliest solution, using a global variable and a normal function.
class CallbackHolder {
public:
void dostuff(void) {
// etc.
}
};
CallbackHolder * g_callbackHolder = NULL;
void call_callback_holder(void) {
if(g_callbackHolder) g_callbackHolder->dostuff();
}
void bind() {
g_callbackHolder = new CallbackHolder();
glutIdleFunc( &call_callback_holder );
}

How to pass a Function pointer without exposing class details

I'm creating a library that needs to allow the user to set a callback function.
The interface of this library is as below:
// Viewer Class Interface Exposed to user
/////////////////////////////
#include "dataType_1.h"
#include "dataType_2.h"
class Viewer
{
void SetCallbackFuntion( dataType_1* (Func) (dataType_2* ) );
private:
dataType_1* (*CallbackFunction) (dataType_2* );
}
In a typical usage, the user needs to access an object of dataType_3 within the callback.
However, this object is only known only to his program, like below.
// User usage
#include "Viewer.h"
#include "dataType_3.h"
// Global Declaration needed
dataType_3* objectDataType3;
dataType_1* aFunction( dataType_2* a)
{
// An operation on object of type dataType_3
objectDataType3->DoSomething();
}
main()
{
Viewer* myViewer;
myViewer->SetCallbackFunction( &aFunction );
}
My Question is as follows:
How do I avoid using an ugly global variable for objectDataType3 ?
(objectDataType3 is part of libraryFoo and all the other objects dataType_1, dataType_2 & Viewer are part of libraryFooBar) Hence I would like them to remain as separate as possible.
Don't use C in C++.
Use an interface to represent the fact you want a notification.
If you want objects of type dataType_3 to be notified of an event that happens in the viewer then just make this type implement the interface then you can register the object directly with the viewer for notification.
// The interface
// Very close to your function pointer definition.
class Listener
{
public: virtual dataType_1* notify(dataType_2* param) = 0;
};
// Updated viewer to use the interface defineition rather than a pointer.
// Note: In the old days of C when you registered a callback you normally
// also registered some data that was passed to the callback
// (see pthread_create for example)
class Viewer
{
// Set (or Add) a listener.
void SetNotifier(Listener* l) { listener = l; }
// Now you can just inform all objects that are listening
// directly via the interface. (remember to check for NULL listener)
void NotifyList(dataType_2* data) { if (listener) { listener->notify(data); }
private:
Listener* listener;
};
int main()
{
dataType_3 objectDataType3; // must implement the Listener interface
Viewer viewer;
viewer.SetNotifier(&objectDataType3);
}
Use Boost.Function:
class Viewer
{
void SetCallbackFuntion(boost::function<datatype_1* (dataType_2*)> func);
private:
boost::function<datatype_1* (dataType_2*)> CallbackFunction;
}
Then use Boost.Bind to pass the member function pointer together with your object as the function.
If you don't want or can't use boost, the typical pattern around callback functions like this is that you can pass a "user data" value (mostly declared as void*) when registering the callback. This value is then passed to the callback function.
The usage then looks like this:
dataType_1* aFunction( dataType_2* a, void* user_ptr )
{
// Cast user_ptr to datatype_3
// We know it works because we passed it during set callback
datatype_3* objectDataType3 = reinterpret_cast<datatype_3*>(user_ptr);
// An operation on object of type dataType_3
objectDataType3->DoSomething();
}
main()
{
Viewer* myViewer;
dataType_3 objectDataType3; // No longer needs to be global
myViewer->SetCallbackFunction( &aFunction, &objectDataType3 );
}
The implementation on the other side only requires to save the void* along with the function pointer:
class Viewer
{
void SetCallbackFuntion( dataType_1* (Func) (dataType_2*, void*), void* user_ptr );
private:
dataType_1* (*CallbackFunction) (dataType_2*, void*);
void* user_ptr;
}
boost::/std:: function is the solution here. You can bind member functions to them, and in addition functors and lambdas, if you have a lambda compiler.
struct local {
datatype3* object;
local(datatype3* ptr)
: object(ptr) {}
void operator()() {
object->func();
}
};
boost::function<void()> func;
func = local(object);
func(); // calls object->func() by magic.
Something like this is simple to do:
class Callback
{
public:
virtual operator()()=0;
};
template<class T>
class ClassCallback
{
T* _classPtr;
typedef void(T::*fncb)();
fncb _cbProc;
public:
ClassCallback(T* classPtr,fncb cbProc):_classPtr(classPtr),_cbProc(cbProc){}
virtual operator()(){
_classPtr->*_cbProc();
}
};
Your Viewer class would take a callback, and call it using the easy syntax:
class Viewer
{
void SetCallbackFuntion( Callback* );
void OnCallCallback(){
m_cb->operator()();
}
}
Some other class would register the callback with the viewer by using the ClassCallback template specialization:
// User usage
#include "Viewer.h"
#include "dataType_3.h"
main()
{
Viewer* myViewer;
dataType_3 objectDataType3;
myViewer->SetCallbackFunction( new ClassCallback<dataType_3>(&objectDataType3,&dataType_3::DoSomething));
}
You're asking several questions mixed up in here and this is going to cause you lots of confusion in your answers.
I'm going to focus on your issue with dataType_3.
You state:
I would like to avoid declaring or
including dataType_3 in my library as
it has huge dependencies.
What you need to do is make an interface class for dataType_3 that gives the operations -- the footprint -- of dataType_3 without defining everything in it. You'll find tips on how to do that in this article (among other places). This will allow you to comfortably include a header that gives the footprint for dataType_3 without bringing in all of its dependencies. (If you've got dependencies in the public API you may have to reuse that trick for all of those as well. This can get tedious, but this is the price of having a poorly-designed API.)
Once you've got that, instead of passing in a function for callback consider having your "callback" instead be a class implementing a known interface. There are several advantages to doing this which you can find in the literature, but for your specific example there's a further advantage. You can inherit that interface complete with an instantiated dataType_3 object in the base class. This means that you only have to #include the dataType_3 interface specification and then use the dataType_3 instance provided for you by the "callback" framework.
If you have the option of forcing some form of constraints on Viewer, I would simply template that, i.e.
template <typename CallBackType>
class Viewer
{
public:
void SetCallbackFunctor(CallBackType& callback) { _callee = callback; }
void OnCallback()
{
if (_callee) (*_callee)(...);
}
private:
// I like references, but you can use pointers
boost::optional<CallBackType&> _callee;
};
Then in your dataType_3 implement the operator() to do as needed, to use.
int main(void)
{
dataType_3 objectDataType3;
// IMHO, I would construct with the objectDataType3, rather than separate method
// if you did that, you can hold a direct reference rather than pointer or boost::optional!
Viewer<dataType_3> viewer;
viewer.SetCallbackFunctor(objectDataType3);
}
No need for other interfaces, void* etc.