Forwarding an object in C++ - c++

I am working on a project with an ESP32 and a MCP23017.
In the main program I create an object for the MCP and initialize the address.
Adafruit_MCP23X17 pin_Expander;
const int expander_addr = 0x20; // Adress 0x20
void setup()
{
Serial.begin(9600);
pin_Expander.begin_I2C(expander_addr);
expander_Init(pin_Expander);
}
Since I use many IOs in the project, I wanted to outsource the initialization of these and wrote a function. I have created a separate header file for the function.
void expander_Init(Adafruit_MCP23X17 pin_Expander)
{
// Load the GPIOs
pin_Expander.pinMode(pin1_Motor1, OUTPUT); // I have removed the other pins
// Set all GPIOs to LOW
pin_Expander.digitalWrite(pin1_Motor1, LOW); // I have removed the other pins
}
I wonder if this is a legitimate way to pass an object into another function?

Adafruit_MCP23X17 is a C++ class, not some typedef that simulates reference semantics in C, so when you declare your function:
void expander_Init(Adafruit_MCP23X17 pin_Expander)
you're accepting the object by value, not by reference, which means expander_Init(pin_Expander); copies pin_Expander and passes in the copy. Any mutations to the copy would not typically affect the original version (unless the class is poorly designed†).
If you want to modify the original version, change the prototype to:
void expander_Init(Adafruit_MCP23X17& pin_Expander)
// ^ added & to make it accept by reference
which means you'll accept a reference to whatever the caller passed, no copies involved, and anything you do to that reference is equivalent to doing it to the original caller-passed object.
† I'll note: I wouldn't be surprised if the class was poorly designed, and all instance methods effectively modified global, not per-instance, state (low-level hardware manipulation can often make assumptions like this), so your original code might work just fine, but it's not guaranteed without source code inspection, and it might involve some inefficiencies in the extra copy-and-destroy work that passing-by-reference avoids.

Related

Run-time exceptions when using std::functions. Why do they not point to valid code?

I am working on putting together a library to enable easy implementation of Finite State Machines.
My library is based upon arduino-fsm, a library that achieves this by defining Fsm, State and Transition objects. arduino-fsm uses raw function pointers to set the functions that States and Transitions will call (functions that cover what to do when: entering a state, in a state, exiting a state, making a particular state transition). This library allows very intuitive state machine definition. However, it's use of raw function pointers means that an Fsm can't usefully be an instance variable of an object (raw function pointers can't point to non-static member functions, and static member functions can't access instance variables - making it impossible to have multiple different parent objects of the same class running different instances of the same Fsm.
My implementation replaces the use of raw function pointers with std::functions to define the States' and Transitions' functions in order to allow this (following answers to this question).
I appear to be falling at the first hurdle, however. I'm having runtime exceptions that my stack backtrace shows are due to my std::functions not pointing to valid code (reference). I can't figure out why this is happening though.
The full code is here, but I'll attempt to describe the code in short and the issue more clearly below.
The library defines the struct FunctionState and class FunctionFsm (FunctionFsm also defines the struct Transition).
FunctionState holds three std::functions called on_enter, on_state and on_exit. The functions they point to are called whenever the FunctionState is first entered, is active and is left, respectively.
FunctionFsm has functions to setup the fsm's transitions, to run the state machine, and to trigger transitions between states. It tracks the current state, and keeps a list of Transitions that define the state machine.
Transitions hold pointers to the state they move from and the state they move to, and 'event' integer (which allows particular Transitions to be triggered) and a std::function that points to a function to be called in that transition (after the first state's exit function is called).
In all, std::functions are used to tell each state what it's three functions are and to tell transitions what function it should use. (If no action is required for any particular state function or transition, the std::function may be set to nullptr - and the library will handle it appropriately.)
My simple example appears to fail in the fsm's setup, when it defines the first transition for the state machine.
Important bits from FunctionFsm in the library:
struct Transition {
FunctionState* state_from;
FunctionState* state_to;
int event;
std::function<void()> on_transition;
};
Transition create_transition(FunctionState* state_from,
FunctionState* state_to,
int event,
std::function<void()> on_transition){
Transition t;
t.state_from = state_from;
t.state_to = state_to;
t.event = event;
t.on_transition = on_transition;
return t;
}
void add_transition(FunctionState* state_from,
FunctionState* state_to,
int event,
std::function<void()> on_transition){
if(state_from == NULL || state_to == NULL) return;
Transition transition = FunctionFsm::create_transition(state_from,
state_to,
event,
on_transition);
//stuff to keep track of number of transitions and add transition to the list
//m_transitions is just a Transition*, manual memory management copied
//like-for-like from arduino-fsm (which doesn't use stdlib features)
m_transitions = (Transition*) realloc (m_transitions,
(m_num_transitions + 1)
* sizeof(Transition));
m_transitions[m_num_transitions] = transition;
m_num_transitions++;
}
Example:
char a = 'a';
char b = 'b';
//state functions
void a_on_enter(){ Serial.print("Entering a: "); }
void a_on(){ Serial.print(a); }
void a_on_exit(){ Serial.println(" - exitting a. "); }
void a_on_trans_b(){ Serial.println("Moving from a to b."); }
void b_on_enter(){ Serial.print("Entering b: "); }
void b_on(){ Serial.print(b); }
void b_on_exit(){ Serial.println(" - exitting b. "); }
void b_on_trans_a(){ Serial.println("Moving from b to a."); }
//states
FunctionState state_a(&a_on_enter, &a_on, &a_on_exit);
FunctionState state_b(&b_on_enter, &b_on, &b_on_exit);
//fsm
FunctionFsm fsm(&state_a); //state_a is initial state
//...
//add transitions
fsm.add_transition(&state_a, &state_b, TOGGLE_SWITCH, &a_on_trans_b);//crashes here
fsm.add_transition(&state_b, &state_a, TOGGLE_SWITCH, &b_on_trans_a);
//... code to run fsm, and trigger transitions as appropriate (hasn't had a chance to run yet)
I note that the crash is occurring on the first attempt to give a std::function a value, which shows that I'm handling it wrong somewhere in the library functions... But I really can't understand it. I don't think the function itself has been called anywhere, it's just that a std::function has assigned it?
The error itself is certainly this (as my microcontroller tells me it is) - I just can't figure out why...
I had wondered if I was asking too much of implicit conversion by providing functions that called for std::function<void()> with raw function pointers, but my testing shows no improvement if I explicitly create std::functions and then pass those instead.
I also worried about whether I'm passing my functions by reference or by value, but I don't think that makes a difference here either.
If anyone with more experience using std::function has any helpful suggestions, I'd be really grateful. I'm quite stuck and don't know how to move forward from here.
Big thank you to #molbdnilo for reminding me to create Minimal, Complete, and Verifiable examples and pointing out the likely cause, which is now confirmed.
It turns out the issue was with the use of a Transition pointer and realloc to keep a list of the fsm's transitions in a very C way rather than using a std::vector<Transition> (much more C++). I'd flagged this initially as poor practice, but hadn't considered the effect it may have had.
I haven't gone into understanding the full details of why using realloc has messed up my std::functions, but I can certainly see the vagueries of where this issue comes from.
Having updated the library to use a std::vector instead, everything works perfectly.
If anyone would like to provide a real explanation of the issue with using realloc in this case I'd be very interested to hear it! (I'd certainly mark it as an answer!)

Disable code based on existence of Constructor

I am trying to disable some code based on whether the code creates an Object or not (or calls a function or whatever). Sounds a bit strange, I know.
In my library it is possible to create 2 objects, each object needs an interrupt service routine like:
ISR(TIMER0_COMPA_vect) {
// do some stuff if the interrupt happens
}
The ISR can only be created once but it could be possible that the user just creates one or none of my objects, so the ISR shouldn't be created in the first place to not block the creation of one by the user.
I know it would be easy to encapsulate the code like this
#ifdef OBJECT1
ISR(TIMER0_COMPA_vect) {
// do some stuff if the interrupt happens
}
#endif
but that forces the user to keep track of the objects she/he created.
Is there an option to let the preprocessor decide if, let's say, the constructor is called once or even existent?
A little bit like something like this
Foo:Foo() {
#define USE_FOO
//Some code
}
#ifdef USE_FOO
ISR(TIMER0_COMPA_vect) {
// do some stuff if the interrupt happens
}
#endif
EDIT:
Based on the answers i got, I try to clarify my question a bit:
Foo1:Foo1() {
//Some object constructor code
}
Foo2:Foo2() {
//Some object constructor code
}
ISR(TIMER1_COMPA_vect) {
//some interrupt code
}
ISR(TIMER2_COMPA_vect) {
//some interrupt code
}
int main() {
Foo2 foo2;
}
If this is the code we are talking about, the function ISR(TIMER1_COMPA_vect) shouldn't be compiled at all. The ISR MUST be absent.
PS: if you need more information, I can provide more but I tried to keep the problem as basic as possible
Typically what you would do for this type of situation is compile the code for such an object into a library. The linker is smart enough to detect if your main program depends on any function from the library. If it does, it will load the entire compilation unit (i.e. the .c or .cpp file) of that function into your program. Any ISRs that it finds in the compilation unit will be added to your program. If you don't use any functions from the library, the ISRs will not be added.
For example, put something like this in foo1.h:
#pragma once
class Foo1 {
public:
Foo1();
};
Put something like this in foo1.cpp:
#include <foo1.h>
ISR(TIMER1_COMPA_vect) {
}
Foo1::Foo1() {
}
Now you should compile foo1.cpp into foo1.o using avr-gcc. Next, use avr-ar to store foo1.o in an archive named foo1.a. Then, compile your main program with avr-gcc, and provide foo1.a as an argument. Make sure the foo1.a argument comes after main.cpp.
You may need to create a singleton. There are numerous examples. A singleton is a class that constructs itself, once only. The constructors are private and a static method checks a "global" variable to see if the class has already been constructed if not it will construct itself once only. You will may need to consider threading issues although for construction you can simply reference the class early before you have created multiple classes. For multiple users of an interrupt you typically use some sort of dispatcher that the objects register with and then all classes interested in the interrupt are called. The dispatcher may be a singleton. Typically a client of a dispatcher implements an interface. As part of registration with the dispatcher the class tell the dispatcher its "this" pointer and the dispatcher can call the methods implemented from the interface as though they were called as normal. There is no need for the client to have static methods. There are probably patterns for this stuff but I cannot name any.
As you stated your problem sounds strange but if you want to do something only once let's say in the constructor you can go with a simple but very ugly thing like this using local static variable
Foo:Foo() {
static bool init = true;
if( init ) {
//Some code for ISR init
init = false;
}
}
This way your special ISR initialization will take place only once, whatever the number of Foo object you or your user construct
EDIT:
I think there is no way to achieve what you want, at least no clean way.
Imo your problem comes from your ISR macro which actually does two things:
Initializing your ISR vector (ISR registration)
Defining your ISR handler (ISR handler)
To solve your problem I suggest you to split this into two macros then:
ISR registration goes in you Foo1 / Foo2 constructor -> use a global field or whatever mechanism to initialize only once or keep track internally of what has happened or so
Keep another macro ISR_HANDLER with only the handler definition
Your handlers can then remain defined and should have no influence if it is not registered by any of the Foo classes

How to use external library in my own Arduino library?

Good evening!
I'm writing an Arduino library. Inside it, I want to instantiate an object from another library whose constructor needs to be passed a parameter, but I don't want to hard-code such parameter. I need some guidance about how to do this.
Here's the relevant part of my code so far:
HSBC_CAN.h:
class HSBC_CAN {
public:
HSBC_CAN(uint8_t, uint8_t);
private:
uint8_t _int_pin;
};
HSBC_CAN.cpp:
#include <HSBC_CAN.h>
#include <mcp_can.h>
extern MCP_CAN *canbus_esc;
HSBC_CAN::HSBC_CAN(uint8_t int_pin, uint8_t cs_pin) {
_int_pin = int_pin;
canbus_esc = new MCP_CAN(cs_pin);
}
To be clear, the way to instantiate an object from MCP_CAN class is MCP_CAN foo(int bar), where bar is the chip select pin number for SPI protocol. I want my library to instantiate an object of MCP_CAN class but I need to be able to pass the chip select pin number when instantiating an object from my new class HSBC_CAN. This is the error I get with the above code:
error: request for member 'begin' in 'canbus_esc', which is of pointer type 'MCP_CAN*' (maybe you meant to use '->' ?)
Probably the way I did in my sample code is totally wrong (with the extern keyword and the new operator) but that's just what came out from my mind ATM.
Thanks for the time.
The error message from the compiler is very useful and if you would follow its advice of replacing . with -> it would probably fix your immediate problem. Since canbus_esc is a pointer, you must dereference it before accessing its members or functions. So if it has a function named begin that can be called with zero arguments, you might write:
canbus_esc->begin();
That line is equivalent to:
(*canbus_esc).begin();
Also, get rid of the word extern on the line that defined canbus_esc, or else you will get an undefined reference error for it.
However, I have two issues with the code you have presented: First of all, you are using new, which does dynamic memory allocation. It's a good idea to avoid dynamic memory allocation on small devices like AVRs if you can, since you never know if those allocations are going to fail until you actually run the program (you might be using up too much memory in other parts of your program). Secondly, you defined your canbus_esc at the file scope, so there can only be one of them. This means you can't really create multiple HSBC_CAN objects; the second one will overwrite the canbus_esc create by the first. Although that might be fine for your application, it seems like a needless limitation.
I'd suggest writing your code like this instead:
Header file:
#include <mcp_can.h>
class HSBC_CAN {
public:
HSBC_CAN(uint8_t int_pin, uint8_t cs_pin);
void begin();
private:
uint8_t _int_pin;
MCP_CAN can;
};
Source file:
#include <HSBC_CAN.h>
HSBC_CAN::HSBC_CAN(uint8_t int_pin, uint8_t cs_pin)
: can(cs_pin) // This line constructs the MCP_CAN object
{
_int_pin = int_pin;
}
HSBC_CAN::begin()
{
can.begin(42, 42, 42); // TODO: fix arguments
}
Another idea, which might be better, would be for you to have your HSBC_CAN object take a pointer to an MBC_CAN object and store the pointer as a member variable in the HSBC_CAN class. That option would make a lot of sense if there are multiple devices on the CAN bus that you want to talk to using that MBC_CAN object. You could have multiple classes using a single MBC_CAN object via pointers.

Choosing data for parcelable in C++

In a previous program that I have written in C I needed a single object with several "core" data in it that can be accessed by all the functions in my program, I end up picking a struct and i have used a pointer to this struct for reading or writing data; it was fast and good for the job, also it was cheap because accessing a pointer is probably one of the cheapest thing that you can do in C and I have never found something better so I'm happy with this solution.
Now in C++ I have the same problem, I need to share a state composed of some primitive types, I'm tempted to use one of the so called POD, which basically mean, struct, again, but this time with references for safety.
Supposing that I need this "Blob" of data to be carried around my program, a struct accessed by reference is the fastest thing in C++? How much a getter methods can cost?
If your getter code is inline (in the header file), then the compiler can eliminate the need to call a function in the machine code it outputs.
eg:
class Data
{
private:
int number_;
public:
int GetNumber() { return number_; }
};
The compiler will see GetNumber's definition, will know what it does is simple and and where you've called GetNumber(), it will simply replace it with number_. So, using a getter versus accessing the member directly will result in the equivalent code, and both will perform the same.

Serializing function objects

Is it possible to serialize and deserialize a std::function, a function object, or a closure in general in C++? How? Does C++11 facilitate this? Is there any library support available for such a task (e.g., in Boost)?
For example, suppose a C++ program has a std::function which is needed to be communicated (say via a TCP/IP socket) to another C++ program residing on another machine. What do you suggest in such a scenario?
Edit:
To clarify, the functions which are to be moved are supposed to be pure and side-effect-free. So I do not have security or state-mismatch problems.
A solution to the problem is to build a small embedded domain specific language and serialize its abstract syntax tree.
I was hoping that I could find some language/library support for moving a machine-independent representation of functions instead.
Yes for function pointers and closures. Not for std::function.
A function pointer is the simplest — it is just a pointer like any other so you can just read it as bytes:
template <typename _Res, typename... _Args>
std::string serialize(_Res (*fn_ptr)(_Args...)) {
return std::string(reinterpret_cast<const char*>(&fn_ptr), sizeof(fn_ptr));
}
template <typename _Res, typename... _Args>
_Res (*deserialize(std::string str))(_Args...) {
return *reinterpret_cast<_Res (**)(_Args...)>(const_cast<char*>(str.c_str()));
}
But I was surprised to find that even without recompilation the address of a function will change on every invocation of the program. Not very useful if you want to transmit the address. This is due to ASLR, which you can turn off on Linux by starting your_program with setarch $(uname -m) -LR your_program.
Now you can send the function pointer to a different machine running the same program, and call it! (This does not involve transmitting executable code. But unless you are generating executable code at run-time, I don't think you are looking for that.)
A lambda function is quite different.
std::function<int(int)> addN(int N) {
auto f = [=](int x){ return x + N; };
return f;
}
The value of f will be the captured int N. Its representation in memory is the same as an int! The compiler generates an unnamed class for the lambda, of which f is an instance. This class has operator() overloaded with our code.
The class being unnamed presents a problem for serialization. It also presents a problem for returning lambda functions from functions. The latter problem is solved by std::function.
std::function as far as I understand is implemented by creating a templated wrapper class which effectively holds a reference to the unnamed class behind the lambda function through the template type parameter. (This is _Function_handler in functional.) std::function takes a function pointer to a static method (_M_invoke) of this wrapper class and stores that plus the closure value.
Unfortunately, everything is buried in private members and the size of the closure value is not stored. (It does not need to, because the lambda function knows its size.)
So std::function does not lend itself to serialization, but works well as a blueprint. I followed what it does, simplified it a lot (I only wanted to serialize lambdas, not the myriad other callable things), saved the size of the closure value in a size_t, and added methods for (de)serialization. It works!
No.
C++ has no built-in support for serialization and was never conceived with the idea of transmitting code from one process to another, lest one machine to another. Languages that may do so generally feature both an IR (intermediate representation of the code that is machine independent) and reflection.
So you are left with writing yourself a protocol for transmitting the actions you want, and the DSL approach is certainly workable... depending on the variety of tasks you wish to perform and the need for performance.
Another solution would be to go with an existing language. For example the Redis NoSQL database embeds a LUA engine and may execute LUA scripts, you could do the same and transmit LUA scripts on the network.
No, but there are some restricted solutions.
The most you can hope for is to register functions in some sort of global map (e.g. with key strings) that is common to the sending code and the receiving code (either in different computers or before and after serialization).
You can then serialize the string associated with the function and get it on the other side.
As a concrete example the library HPX implements something like this, in something called HPX_ACTION.
This requires a lot of protocol and it is fragile with respect to changes in code.
But after all this is no different from something that tries to serialize a class with private data. In some sense the code of the function is its private part (the arguments and return interface is the public part).
What leaves you a slip of hope is that depending on how you organize the code these "objects" can be global or common and if all goes right they are available during serialization and deserialization through some kind predefined runtime indirection.
This is a crude example:
serializer code:
// common:
class C{
double d;
public:
C(double d) : d(d){}
operator(double x) const{return d*x;}
};
C c1{1.};
C c2{2.};
std::map<std::string, C*> const m{{"c1", &c1}, {"c2", &c2}};
// :common
main(int argc, char** argv){
C* f = (argc == 2)?&c1:&c2;
(*f)(5.); // print 5 or 10 depending on the runtime args
serialize(f); // somehow write "c1" or "c2" to a file
}
deserializer code:
// common:
class C{
double d;
public:
operator(double x){return d*x;}
};
C c1;
C c2;
std::map<std::string, C*> const m{{"c1", &c1}, {"c2", &c2}};
// :common
main(){
C* f;
deserialize(f); // somehow read "c1" or "c2" and assign the pointer from the translation "map"
(*f)(3.); // print 3 or 6 depending on the code of the **other** run
}
(code not tested).
Note that this forces a lot of common and consistent code, but depending on the environment you might be able to guarantee this.
The slightest change in the code can produce a hard to detect logical bug.
Also, I played here with global objects (which can be used on free functions) but the same can be done with scoped objects, what becomes trickier is how to establish the map locally (#include common code inside a local scope?)