How to pass a delegate^ to a native class in c++/cli - c++

I have a native class
public NativeClass:
{
public:
typedef void(*Func)(cv::UMat image);
void setFunc(Func func);
}
and would like to pass a function as parameter from managed class.
ref ManagedClass:
{
public:
ManagedClass()
{
NativeClass* nativeClass = new NativeClass();
nativeClass.setFunc(doSomething);
}
private:
doSomething(cv::UMat image)
{
//do something
}
}
But it seems to not work. How can I get this to work?

Before you pass the delegate as a function pointer, you need to create a delegate first.
In C#, you just need to reference the method name without parenthesis. In C++/CLI, you need to explicitly call the delegate constructor, and you need to pass explicit parameters of the object to call the method on, and the method in a C++-style.
MyDelegate^ del = gcnew MyDelegate(this, &ManagedClass::doSomething);
// Explicit ctor ^^^^^^^^^^^^^^^^
// Pass the object to be called on ^^^^
// Pass the method in the C++ style ^^^^^^^^^^^^^^^^^^^^^^^^^^
Once you have that, you can just pass the delegate to the method that takes a raw function pointer. It knows how to convert the managed delegate object to a function pointer. There's a good example in Microsoft's documentation. You must be sure to keep around the managed delegate object forever. As soon as the managed delegate is garbage collected, the raw function pointer stops working.
Once you have that, you'll need to look at your parameter type, cv::UMat. I don't know what type that is or where you're getting it, but you may need to adjust your parameter type on the managed side, the unmanaged side, or both. (This is why I didn't declare the delegate type in my example above; I wasn't sure what would work so I left it generic. If everything works, then you might be able to use Action<cv::UMat> as your delegate type.)

Related

How would I use a library that extends libev in a C++ object?

I am trying to implement a wrapper for a library called libumqtt. Libumqtt is a C library that uses libev to have callbacks for events from the MQTT protocol.
What I didn't realize until the other day is that I cannot pass a member function to a function that expects a normal, static function. This causes problems as I was planning on launching multiple instances of libumqtt to handle multiple connections at the same time.
My code is in C++ as that is the most convenient to use with the Godot's (a game engine) GDNative module.
While researching for either a way to sandbox multiple instances of a c library or to somehow get the pointers to work anyway, I found this answer. I do not understand this quote from the answer:
If you need to access any non-static member of your class and you need
to stick with function pointers, e.g., because the function is part of
a C interface, your best option is to always pass a void* to your
function taking function pointers and call your member through a
forwarding function which obtains an object from the void* and then
calls the member function.
What I am trying to do is setup callbacks that libev will use to send the data to the right instance of my object when it is handling potentially up to 500 or more connections simultaneously.
Will passing void* help me with my goals and how would I implement this? Also, how does a forwarding function work?
Edit: To Provide Code Example That Walnut Is Asking For
This example below comes from a version of my class that uses static functions. If I tried to use run this when the functions are not static, then I would get an error about not being able to pass in a member function in place of a regular function.
// Client.cpp
void Client::signal_cb(struct ev_loop *loop, ev_signal *w, int revents) {
ev_break(loop, EVBREAK_ALL);
}
// ...
void Client::do_connect(struct ev_loop *loop, struct ev_timer *w, int revents) {
//Godot::print("Attempt MQTT Start!!!\n");
//write_log("debug", "MQTT Wrapper - Attempt MQTT Start!!!");
struct umqtt_client *cl; // Move to Class Access (Private)?
cl = umqtt_new(loop, cfg.host, cfg.port, cfg.ssl);
if (!cl) {
//Godot::print("Failed To Create Client!!!\n");
//write_log("debug", "MQTT Wrapper - Failed To Create Client!!!");
start_reconnect(loop);
return;
}
//Godot::print("Setup Client Callbacks!!!\n");
//write_log("debug", "MQTT Wrapper - Setup Client Callbacks!!!");
// For StackOverflow: These cl->... lines do not work because of not being able to pass a member function as a regular function. These are the main callbacks I have trouble with.
// How do I convert from `void (libumqtt::Client::*)(struct umqtt_client *)` to `void (*)(struct umqtt_client *)`?
cl->on_net_connected = Client::on_net_connected; // Pass member function as a non-static object
cl->on_conack = Client::on_conack; // Pass member function as a non-static object
cl->on_suback = Client::on_suback; // Pass member function as a non-static object
cl->on_unsuback = Client::on_unsuback; // Pass member function as a non-static object
cl->on_publish = Client::on_publish; // Pass member function as a non-static object
cl->on_pingresp = Client::on_pingresp; // Pass member function as a non-static object
cl->on_error = Client::on_error; // Pass member function as a non-static object
cl->on_close = Client::on_close; // Pass member function as a non-static object
//Godot::print("MQTT Start!!!\n");
//write_log("debug", "MQTT Wrapper - MQTT Start!!!");
}
void Client::initialize() {
// For StackOverflow: These two lines cannot work in an object as libev expects signal_cb and do_connect to be regular functions. These callbacks are also necessary, but I am not sure how to handle this.
ev_signal_init(&signal_watcher, Client::signal_cb, SIGINT);
ev_timer_init(&reconnect_timer, Client::do_connect, 0.1, 0.0); // Fix Me - Make ev.h object
// ...
}
Edit: I should mention I am a noob at using C and C++. The most I've done in it before is testing a buffer overflow. So, if their's anything I am obviously doing wrong, I would appreciate the tip in the comments.
So the issue is that umqtt_client does not seem to provide any way of passing additional user data to the callback (the void* mentioned in your quote). It expects the callback to take just a pointer to the umqtt_client instance. (I may be wrong here, I am basing this just on a quick look at the source files.)
If your member functions don't actually access any non-static member of your class, then you can simply make them static. Then you can use them directly as normal function pointers.
Otherwise you need to obtain a pointer to your instance from the umqtt_client* pointer.
One way of doing this would be to maintain a static map between the pointers, e.g. in Client add a declaration:
static std::map<umqtt_client*, Client*> umqtt_client_map;
and insert into it when creating a Client (I will assume here that you actually maintain the cl pointer as class member of Client), preferably in Client's constructor:
umqtt_client_map[cl] = this;
Then in Client's destructor (or where ever the umqtt_client object is destroyed) erase the corresponding element from the map:
umqtt_client_map.erase(cl);
Then you can use a lambda looking like this to pass as callback:
cl->on_net_connected = [](umqtt_client* ptr){
umqtt_client_map[ptr]->on_net_connected();
};
Note that on_net_connected won't need the pointer as argument if it is a member of the class.
This also assumes that you make the class non-copyable and non-movable or that you implement the copy- and move-constructor and -assignment operators with the correct semantics of erasing and inserting into umqtt_client_map as well.
The library seems to offer a function umqtt_init instead of umqtt_new that doesn't allocate the umqtt_client object. If you use that instead you could do the following:
Wrap the umqtt_client in a small standard-layout class:
struct umqtt_client_wrapper {
umqtt_client cl; // must be first member!
Client* client;
static_assert(std::is_standard_layout_v<umqtt_client_wrapper>);
};
You would then use that as member of Client instead of umqtt_client* directly and initialize the umqtt_client* with umqtt_init) andclientwiththisinClient`'s constructor. Then you can use a cast in the lambda for the callback:
cl->on_net_connected = [](umqtt_client* ptr) {
reinterpret_cast<umqtt_client_wrapper*>(ptr)->client->on_net_connected();
};
Note that this depends on umqtt_client_wrapper being standard-layout and that umqtt_client* is its first member. Not following these rules will cause undefined behavior. The static_assert gives some assurance that at least part of it is not accidentally violated. It requires #include<type_traits> and C++17 in the form that I used here.
Again this requires special care to implement the copy- and move- special member functions of Client correctly or to delete them, but with this method no action in the destructor is required.
This approach is more performant than the other one and in principle you could avoid the extra Client pointer if you make sure that Client itself is standard-layout, but that is probably too restrictive and risky.
Another way, saving the extra indirection, is to use the wrapper as a base class of Client:
struct umqtt_client_wrapper {
umqtt_client cl; // must be first member!
static_assert(std::is_standard_layout_v<umqtt_client_wrapper>);
};
Then let Client inherit from umqtt_client_wrapper and you can use:
cl->on_net_connected = [](umqtt_client* ptr) {
static_cast<Client*>(reinterpret_cast<umqtt_client_wrapper*>(ptr))
->on_net_connected();
};
Note that here the first cast must be static_cast, otherwise you could easily cause undefined behavior.
The same remarks as before apply.

C++ passing overloaded operator() of class as function pointer

So I got myself onto shaky ground by insisting on making a C++ class immitate a regular function. The class overloads the function operator, making it a functor, of course. This all works fine, until you want to pass the function pointer of this functor.
Naturally, I want to let the compiler know that we know what we're doing (lol), by doing a reinterpret_cast of this pointer. However, how do I get the address of this particular member function, since it is an overloaded operator. How does one get the address of that?
UPDATE: You asked for an example. Here is a minimal one.
So I have an interface, which I cannot change. It looks like this;
typedef void (*some_callback_t)(SomeType);'
void someFunc(some_callback_t);
Now, this is quite straight-forward; the API is setting some callback function pointer. So, the idea was to implement the callback as a functor class, by overloading the operator(), like so, as usual.
class Bah {
void operator()(SomeType);
};
Here comes the question; seeing as I cannot change the API used (the function that expects a function pointer of a certain signature), how can I then get the address of the member function and pass that?
I suspect it goes something like;
someFunc(reinterpet_cast<some_callback_t>( ? ? ? )); to make sure that the compiler won't barf at me.
Supposing that you have to use a function pointer, and that your functor has no state, you can use a lambda as glue:
void takesFunctionPointer(void (*)());
struct MyFunctor {
void operator()();
};
// ...
takesFunctionPointer([] { return MyFunctor{}(); });
How does one get the address of that?
In the same way as any other member function. The name of the function is class_name::operator(). An example:
struct class_name {
void operator()(){}
};
void (class_name::*member_function_pointer)() = &class_name::operator();
class_name instance;
(instance.*member_function_pointer)(); // in a block scope
Naturally, I want to let the compiler know that we know what we're doing (lol), by doing a reinterpret_cast of this pointer.
That's usually not what one would want to do.

Trying to make a callback for a member

I have the class stickyNotes, and in it I have the function addNote which is a public non-static function.
In the code there is a new type defined:
typedef void(*fptr)
I also have the class Button which in its constructor takes a variable of type fptr, I have a function makeButton() that returns a Button object.
stickyNotes also has another member called rendermainWindow which renders the main window and adds a button, I am trying to create a new variable of type fptr that is set to the address of stickyNotes::addNote and I'm getting the error:
'&': illegal operation on bound member function expression
stickyNotes::rendermainWindow:
void stickyNotes::rendermainWindow() {
/*
Renders the main window
*/
this->buttonList.empty(); // buttonList is a list of all buttons
mainWindow->clear(sf::Color(29, 29, 27, 255)); // clearing the window
sf::Vector2u windowDimensions = mainWindow->getSize(); // getting window dimensions
fptr cb = &this->addNote; <-------- ERROR HERE
Button plusB = makeButton((int)(windowDimensions.x * 0.75),
(int)(windowDimensions.y * 0.15),
(int)(windowDimensions.x * 0.85),
(int)(windowDimensions.y * 0.25),
mainWindow,
cb);
// first button to add stuff
std::vector<Button> vect;
vect.push_back(plusB);
this->buttonList.push_back(vect);
renderNotes();
}
What I've tried:
Replacing this->addNote with stickyNotes::addNote.
PS:
I'm not looking to make addNote static. and I want to keep it public, how can I make a button with the callback function of addNote?
if there is a workaround, I'll be glad to hear it.
You are trying to pass a callback to the button. If you require the callback to be a simple function pointer (that does not receive any arguments) then your callback cannot retain any state.
However, all non-static member functions require at least one piece of state in order to be called: They need to know which object to work in/with.
These two are fundamentally at odds: If your button takes a simple function pointer, it cannot be used to call member functions (leaving horrible hacks such as global state aside).
One way around this is to use member function pointers: These specify which class they operate on (i.e. are member functions of) and must be called on an instance of that class. Since you presumably want the button callback to be usable with more than one class, you can use polymorphy - this is the interface solution SHR suggested.
Another option for the button interface is to take (and store) a std::function<void()> instead of your function pointer. std::function can store state and is very conveniently used with lambda functions:
Button plusB = makeButton(/* ... */, [this]() { addNote(); });
Lastly, you could allow users to pass some "custom data" to the button interface, possibly as void* or std::any which is passed along to the callback. The user can then store e.g. the stickyNotes instance in that custom data. That is compatible with a simple function pointer. However, this approach circumvents type safety and is very low-level. It is used in some libraries as it is very general, but it's much more annoying to work with than the std::function approach.
The problem:
Member functions are just an offset in the class namespace, so you can't give an offset as absulute address.
Solution 1:
Easy way is to create an Interface, implement it in your class, and return or assign this as the Interface.
Solution 2:
Other option is to create pointer to member function.
for example: void (Class::*pfunc)() will declare pfunc pointer which can point to member function of class Class like void Class::Member()
Solution 3:
As suggested by #GoswinvonBrederlow in the comment, use lambda and return or assign it as std::function:
std::function<void ()> Class::f()
{
return []() { /* do something...*/ };
}

Pass a non-static method pointer as an argument to another method

Sorry to ask such a question as I'm sure it's been answered before, but I'm struggling to find an answer and it's not for the want of looking... anyway..
class foo
{
void read(void (*func)(obj&))
{
// many things happen to obj...
(*func)(obj); // Calls the function pointer to the handler.
}
};
class bar : public foo
{
void handler(obj&)
{
//
}
};
void main()
{
foo f;
typedef void (foo::*funcptr)(obj&);
funcptr ptr = &foo::handler;
f.read(ptr); ????
}
So basically, all I'm trying to do is pass the non-static member method called handler as a function pointer to the read method, so that when the callback is executed, the handler is called.
I've tried all sorts of ways to make this work and don't want to make static methods (for reasons I won't go into). I think I'm pretty close, but have sort of fallen over right at the end! Any help would be appreciated.
You cannot do that: unlike static functions that can be called on their own, the call of a member function requires knowledge of two things - the function being called, and the object on which to call it. That is why it is not possible to pass a member function to an API expecting a "plain" function pointer.
If you do not have access to the source of the foo class, you can create a static function that calls a member function on an object stored at a well-known location (i.e. in a static variable). If you do, consider changing the API to take a function object, similar to what functions from the standard C++ library do.
Finally, there is a common approach used in C libraries that take function pointers - passing an additional void* pointer, which will be passed back in a call to your function pointer; pthreads library does that. If this is the case, you can create a struct that wraps the invocation target object, and pass a pointer to this struct to be passed back to your static function.
AFAIK I don't think there is any other way. You will have to make the method static.

std::bind inside of a class, general concept of an event system

I'm working on a library that's based upon a simple event-system.
For work with GUI elements ("controls"), these are needed a lot. For example, the Window class has got a bunch of events, like "onMouseMove", "onKeyPress", "onKeyRelease", .. However, the basic class for controls is the Control class. It has a virtual function draw (which obviously draws the control) and a virtual function connect which connects the control's and the main window's events (works similar to the Qt Signal-Slot-Concept).
But since the Event class takes an std::function<...> pointer as subject (=> Slot), I cannot simply connect a member function of a derived control class with an event of the window. As a workaround, I'm doing the following thing:
class A : public Control {
friend class Window;
public:
A(){
this->eventHandler = [this] () -> void {
if ( someCondition ) this->onSomeCondition.notify();
};
}
Event<> onSomeCondition;
protected:
std::function<void()> eventHandler;
void connect(Window *window){
window->onSomeHigherEvent.attach(&this->eventHandler);
}
void draw(...) const{
drawSome(...);
}
};
What this basically does is that it assigns a lambda function to the std::function<...> in the constructor and attaches that std::function<...> to the chosen event.
There is a major problem though: What happens if I instantiate a few more objects of that class? If I had the event handlers specified in the class, as a normal function like so:
void eventHandler() {
if ( someCondition ) this->onSomeCondition.notify();
}
And could assign that function to the std::function<...> using std::bind, which does not work for some reason, at least as long as I'm using the following call:
std::bind(&A::eventHandler, this, std::placeholders::_1); // *this will not work since that's just a (reference to the?) copy to of the object.
Anyways, the lambda-function-workaround seems to be less time efficient since it's not really built into the class. Is there a more efficient way to solve this problem? Maybe not by solving the lambda-function problem in particular but by changing the concept?
I'm not sure what your asking, since I can't find the question, but ...
std::bind(&A::eventHandler, this, std::placeholders::_1); // *this will not work since that's just a (reference to the?) copy to of the object.
This creates a callable object that has one unbound parameter, i.e. it expects to be called with one argument, which is not compatible with std::function<void()> because that is a function that expects to be called with no arguments. It's also not compatible with the eventHandler member function you show, because that too takes no arguments.
Maybe you just want to use std::bind(&A::eventHandler, this);