Is there a possibility to call a member function, say the output over UART, to be triggered by an interrupt?
Normally I would have used the TIMER0_COMP vect but I can't seem to get it to work with objects.
SomeClass theObject;
// ...
ISR(USART_RX_vect)
{
theObject.someMethod();
}
Is this what you're looking for?
There is no way to have an interrupt vector point to a specific object's member function. This is due to the fact that it is not possible to pass the *this pointer to an ISR directly.
It is possible to have the interrupt vector point to a specific class's member function, provided that it is a static function that returns void and has no parameters. However, as it's a static function it has no access to any individual object's non-static data members.
Here's an example for an IAR compiler and a timer interrupt vector from an AVR:
class theClass
{
public:
...
#pragma vector=TCC1_CCA_vect
__interrupt static void isrTimer1CompareA(void);
...
}
Again, the limitations with this approach are that the ISR can only access static data for the class.
If you're looking to have the interrupt to relate to a specific object, you'll need something along the lines of what H2C03 recommends, which is having the ISR know about the specific object, then calling a member of that object in the ISR itself.
Related
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.
The const member function guarantees that no member variables can be changed by the member function unless they are marked as mutable.
That being said it guarantees nothing else?
Here is a real example. I have a classes EventHandler and EventDispatcher.
class EventHandler
{
public:
void registerHandler(EventHandler* handler) const // Should this be a const?
{
EventDispatcher::registerHandler(handler);
}
};
EventDispatcher // Singleton Class
{
public:
void registerHandler(EventHandler* handler)
{
mListeners.push_back(handler);
}
private:
std::vector<EventHandler*> mListeners;
};
Should EventDispatcher's registerHandler(EventHandler*) be const? It does not change its member variables, but it does change global state.
Correct, it makes no guarantees about any other state than the object itself. And I would say that there's no particular requirement that it doesn't modify global state. [If you take it to extremes, any function call does modify the current state of the processor - even if it's just storing the return address on the stack [1]].
But a more reasonable thing would be that a const member function like this:
class myclass
{
private:
std::vector<int> v;
public:
std::vector<int> getV() const { return v; }
};
This will create a copy of the vector v - which in turn allocates memory (thus changing global state). An output function that feeds your object to a output stream would be a similar thing.
If a member function modifies some global state (in a way that isn't obvious), then it probably should be made clear in the description of the function (documentation is useful sometimes).
[1] Of course, the C++ and C standards do not state that the processor has to have a stack, return addresses, etc - the compiler could inline all the code, and not make any "calls" at all, or use magic to "remember" where to get back to - as long as the magic actually works, it's fine to rely on that.
Edit based on your edited question:
It's one of those that isn't entirely obvious in either direction, you would expect the registerHanlder to do something like "store the handler object somewhere". But since it's not modifiying the object itself, it may help to explain that it's updating the dispatcher class. Of course, if it's not actually updating the class itself, or using anything from the class, you probably should make it static rather than const - that way it's clear that it's not actually modifying the object itself.
Aside: As it is written, your code won't work, since EventDispatcher::registerHandler is not a static member, and your EventHandler::registerHandler is not referring to an instance of EventDispatcher. You would either have to make an instance of EventDispatcher as a global variable, or make EventDispatcher::registerHandler a static function and make mListeners a static member. Or something else along those lines.
What does the const keyword behind a method declaration guarantee?
The guaranty is a contractual reminder, rather than 'physical' memory barrier.
Thus, if you implement the const keyword correctly, the compiler will be able to help you to detect possible bugs.
However, no C/C++ compiler will stop you from modifying the member state directly; neither via fields nor by casting the object reference to a pointer and modifying the underlying memory.
Is my const method allowed to change (local/global) state?
A const method is not allowed to change the external behaviour of the system, but it is perfectly acceptable for a const method to change the internal state.
In other words, after calling all const methods randomly a couple of times, the system should still provide the same behaviour it did initially.
On the other hand, if the const method feels like caching a time consuming calculation and reuse it for the next call, it should be allowed. Same goes for a logger class that logs statistics, but does not change the behaviour of the system.
So, my problem is this:
I have a class called NetworkInterface that is built using the RakNet networking library.
It holds a method that uses the while loop that RakNet uses to send and receive data.
Now, I made the NetworkInterface class a singleton because I want it to only exist once throughout my game I'm writing.
But, if I'd just call the method with the while loop it would stop my whole gqme so thqt's why I wanted it to run on a different thread so it doesn't interfere with the game mechanics.
Now, I used the std::thread object to start the method in NetworkInterface on a different thread but it throws the C3867 error which states that the method needs to be static or some sort (I found this on Google already) but I don't know how to fix this because I have variables that are used in that method that can't be static as well.
I hope this is clear. In short, how would I implement a non-static method from a class in a seperate thread of my program. Or is there a better way? (I don't want to use the Boost library if that pops up)
You need to provide an object for you to call a non-static member function, just as you can't call method() on its own. To provide that object, pass it to std::thread's constructor after the argument where you put the function.
struct Test {
void func(int x) {}
};
int main() {
Test x;
std::thread t(&Test::func, &x, 42);
t.join();
}
LIVE EXAMPLE
Notice that I've passed &x. This is because non-static class functions accepts a pointer to the object where it is being called from, and this pointer is the this pointer. The rest, which is 42, is the arguments that corresponds to the method's parameter declaration with 42 coinciding with int x in the example.
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.
I have a static function that needs to access data members of a class. The function can be a member, non member or friend function of the class, but it must be static and it cannot take any arguments. So I cannot pass the data members to it as a parameter nor can I pass the object itself to it.
#include "sundials.h"
#include "CVode.h"
class nBody
{
private:
double masses[];
double** paths;
static int accelerator();
//...
public:
//...
void runODE();
};
int nBody::accelerator()
{
// code that needs to know the values stored in masses[]
}
void nBody::runODE()
{
//...
ODEsetAccelerator(accelerator); //require accelerator to be static int
//with specific parameters
// run the ODE
//record trajectories in paths[][]
}
accelerator is fed to a separate ODE solver which requires accelerator to be type static int and take specified arguments, So I can't pass the masses into accelerator because it will be called by the ODE and not main
is there any way I could make the accelerator function know what the value of masses? I don't care how indirect it is.
Let me start off saying your design is broken. A static method that needs to access non-static members of a class and can't receive parameters?
That aside, sure you can. You can access a global object from inside the static method, that's set to the current object you're trying to manipulate:
extern nBody* currentBody;
//........
int nBody::accelerator()
{
//access currentBody
//since this is a member, you have access to other private members
}
//....
nBody someBody;
currentBody = &someBody;
nBody::accelerator();
If this is the "sundials" and "CVode" that show up on a quick web search:
Use the relevant nBody* as the user_data parameter.
It's described in the documentation of the user function (page 55).
If not, please disregard this answer.
Given your constraints, a horrible solution would be to have a static variable in the class called something like currentNBody of type nBody * and set this to the appropriate instance before running the ODE solver.
You are correctly identifying this as a global variable. Of course this will fail utterly if you're doing anything multi-threaded.
This is what i think you are talking about:
Some processing is creating nBody objects with masses.
Some other processing needs to 'accelerate' them.
You need a way essentially to 'register' nBody objects with the 'acceleration process'.
That could be a static method on the AccelerationProcess object or via some callback via RMI, etc.
It is the accelerator process that holds in its state the nBody object references and thus no reason to have a static method on nBody. That is assuming the objects all live in the same memory space - otherwise things get more complicated.