Class with Arduino, use SoftwareSerial as variable - class

Trying to use a class in Arduino 1.0 and setting SoftwareSerial as a variable with no success.
class SensorGPS: public Thread
{
private:
SoftwareSerial* serialGPS; // RX, TX
public:
SensorGPS()
{
serialGPS = new SoftwareSerial(10,11);
serialGPS.begin(4800);
}
}
serialGPS.begin returns the error
arduino_sketch.ino: In constructor 'SensorGPS::SensorGPS()':
arduino_sketch:31: error: request for member 'begin' in '((SensorGPS*)this)->SensorGPS::serialGPS', which is of non-class type 'SoftwareSerial*'
arduino_sketch.ino: In member function 'virtual void SensorGPS::run()':
arduino_sketch:37: error: request for member 'read' in '((SensorGPS*)this)->SensorGPS::serialGPS', which is of non-class type 'SoftwareSerial*'
arduino_sketch:44: error: request for member 'write' in '((SensorGPS*)this)->SensorGPS::serialGPS', which is of non-class type 'SoftwareSerial*'
If remove * when setting the variable
SoftwareSerial serialGPS(10,11); // RX, TX
result error on the variable
arduino_sketch:21: error: expected identifier before numeric constant
arduino_sketch:21: error: expected ',' or '...' before numeric constant
This issue is on all kind of classes that needs values as initialisations. Another example with Dht11 module(1); generates same error.

Notice the same issue with example Dht11 library. So I changed the constructor (library https://github.com/adalton/arduino/tree/master/projects/Dht11_Library).
Example Dht11 open the Dht11.h
From
Dht11(uint8_t newPin) : humidity(-1), temperature(-1), pin(newPin) { }
To (with added function setPin)
Dht11() : humidity(-1), temperature(-1), pin(-1) { }
void setPin(uint8_t newPin) {
pin = newPin;
}
So now in Arduino sketch I can set the pin before usage. This solution is possible to do for the majority of libraries.
class SensorTemperatureHumidity: public Thread
{
private:
static const int Pin = 3;
Dht11 module;
public:
SensorTemperatureHumidity() {
module.setPin(Pin); // Set my pin usage
}
}

Related

Instantiate class at compile time and modify at runtime

I curiously couldn't find anything on this but I want to initialize a class at compile time with constexpr. The class however should be later modifiable at runtime. In essence, the constructor of the class Light is constexpr, while other member vars are not. Additionally, the class initializes an array of member classes which are also "half constexpr / half modifiable". The following gives me various errors but I can't figure out what to change:
Code:
struct A
{
int a;
double b;
};
class Color
{
std::vector<A> points_; <-- modify later
/* const part */
const std::string name_;
public:
constexpr Color(std::string name) : name_(std::move(name)) {}
};
class Light
{
void foo();
int a = 5;
/* const part */
std::array<Color, 3> colors_ = { Color("blue"), Color("red"), Color("yellow") };
};
constexpr Light some_light; // <-- how to make this possible?
Compiling this in gcc yields the following errors:
<source>: In constructor 'constexpr Color::Color(std::string)':
<source>:19:19: error: invalid type for parameter 1 of 'constexpr' function 'constexpr Color::Color(std::string)'
19 | constexpr Color(std::string name) : name_(std::move(name)) {}
| ^~~~~
In file included from /opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/string:55,
from <source>:2:
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/basic_string.h:77:11: note: 'std::__cxx11::basic_string<char>' is not literal because:
77 | class basic_string
| ^~~~~~~~~~~~
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/bits/basic_string.h:77:11: note: 'std::__cxx11::basic_string<char>' has a non-trivial destructor
<source>: At global scope:
<source>:32:17: error: the type 'const Light' of 'constexpr' variable 'some_light' is not literal
32 | constexpr Light some_light; // <-- how to make this possible?
| ^~~~~~~~~~
<source>:22:7: note: 'Light' is not literal because:
22 | class Light
| ^~~~~
<source>:22:7: note: 'Light' has a non-trivial destructor
Compiler returned: 1
How can I make ´Light´ instantiable at compile time (if possible)?

Unable to bind rvalue reference arguments in member function

I'm using pybind11 to create python bindings for a C++ library whose source I cannot change. It contains a class that defines member functions with rvalue reference arguments (eg T &&val). I am unable to create a binding to a member function with rvalue reference arguments but binding to a non-member function with identical arguments works as expected.
A simplified example looks like this:
struct Foo {
// Cannot create a pybinding for this method.
void print_ref(int &&v) const {
std::cout << "Foo::print_ref(" << to_string(v) << ")" <<std::endl;
}
};
// Pybinding for standalone function works as expected.
void print_ref(int&& val) {
std::cout << "print_ref(" << to_string(val) << ")" << std::endl;
};
The pybind11 code looks like this:
PYBIND11_MODULE(refref, m) {
py::class_<Foo>(m, "Foo")
// Both of these attempts to create a pybinding FAILs with same error.
.def("print_ref", &Foo::print_ref)
.def("print_ref", (void (Foo::*) (int&&)) &Foo::print_ref);
// This pybinding of standalone function is SUCCESSful.
m.def("print_ref", &print_ref);
}
The compilation error on the first binding attempt is:
pybind11/bin/../include/site/python3.4/pybind11/pybind11.h:79:80: error: rvalue reference to type 'int' cannot bind to lvalue of type 'int'
initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(args...); },
^~~~
pybind11/bin/../include/site/python3.4/pybind11/pybind11.h:1085:22: note: in instantiation of function template specialization 'pybind11::cpp_function::cpp_function<void, Foo, int &&,
pybind11::name, pybind11::is_method, pybind11::sibling>' requested here
cpp_function cf(method_adaptor<type>(std::forward<Func>(f)), name(name_), is_method(*this),
^
refref.cpp:31:3: note: in instantiation of function template specialization 'pybind11::class_<Foo>::def<void (Foo::*)(int &&) const>' requested here
.def("print_ref", &Foo::print_ref);
Any ideas on what I may be doing wrong? Since it works fine with non-member functions, I'm inclined to suspect a pybind11 issue but thought I would check here first.
Indeed, the problem comes from rvalues. I learned quite a few things from this SO answer and this blog post.
There's a nice workaround : you can create a wrapper class that will redirect calls to the C++ library you cannot change, taking care of the rvalue with the std::move semantic.
#include <iostream>
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
namespace py = pybind11;
struct Foo {
void print_ref(int&& v) const {
std::cout << "Foo::print_ref(" << +v << ")" <<std::endl;
}
};
// This class will interface between PyBind and your library
class Foo_wrap{
private:
Foo _mimu;
public:
void print_ref(int v) const{
_mimu.print_ref(std::move(v));
}
};
PYBIND11_MODULE(example, m) {
py::class_<Foo_wrap>(m, "Foo_wrap")
.def(py::init())
.def("print_ref", &Foo_wrap::print_ref);
}
That you can call in Python with
import example as fo
wr = fo.Foo_wrap()
wr.print_ref(2)

Class in parameter of function (Arduino) does not compile

I am trying to create a simple class in C++, but I keep getting the compilation errors:
main:2: error: variable or field 'doSomething' declared void
main:2: error: 'person' was not declared in this scope
main:
class person {
public:
int a;
};
void doSomething(person joe) {
return;
}
main() and stuff would go here, but even if I include main(){}, the errors still occur. I also tried adding 2 closed parentheses after joe, but then that creates the error:
main: In function 'void doSomething(person (*)())':
main:8: error: request for member 'a' in 'joe', which is of non-class type 'person (*)()'
Any help is greatly appreciated. (I hope this isn't something really stupid I'm missing, because I've been researching for hours).
Edit: I found out this is an Arduino-specific error. This post answers it.
I found out after reading this post that a way to work around this is:
typedef struct person{
public:
int a;
};
void doSomething(void *ptr)
{
person *x;
joe = (person *)ptr;
joe->a = 3; //To set a to 3
//Everything else is normal, except changing any value of person uses "->" rather than "."
return;
}
main()
{
person larry;
doSomething(&larry);
}
So essentially it is:
-Change class to typedef struct
-in the parameter, replace newtype with void *something
-add person *x; and x = (person *)ptr; to the beginning of the function
-whenever accessing type property, use -> rather than .
I'm not a expert but when I try to do what you want to do, I do it this way:
//create an instance of my class
MyAwesomeClass myObject;
void myFunction(MyAwesomeClass& object){
//do what you want here using "object"
object.doSomething();
object.doSomethingElse();
}
void setup() {
//setup stuff here
myObject.init();
}
void loop() {
//call myFunction this way
myFunction(myObject);
}
As I said, I'm not a C++ expert but it does the job.
Hope it helps!
My guess is, you have an invalid syntax error somewhere in the declarations above "class person...". Can you copy and paste the whole file?

Is it possible to have an exported function in a DLL return a static member of an exported class?

I'm working on a plug-in protocol of sorts. The idea is that there's a base clase PCOperatorBase and that plugins would subclass this base class to provide specific functionality through a "process" virtual method that they override. The subclasses also should have a static struct member that hold typical plugin info: plug name, type and subtype. This info is used by another class (a PCOperatorManager) to know what types of plugins is dealing with. And I thought about having it be a static member so that there's no need to instantiate a plug to merely find out about the type of operator it is.
I have the following classes:
PCOperatorBase.h the superclass from which to derive all other plugs:
#ifdef PCOPERATORBASE_EXPORTS
#define PCOPERATORBASE_API __declspec(dllexport)
#else
#define PCOPERATORBASE_API __declspec(dllimport)
#endif
class PCOPERATORBASE_API PCOperatorBase
{
public:
typedef struct OperatorInfo
{
wchar_t* name;
wchar_t* type;
wchar_t* subtype;
} OperatorInfo;
PCOperatorBase(void);
virtual ~PCOperatorBase(void);
virtual int process(int* inBuffer, int* outBuffer, int bufferSize);
};
And then, for instance, a subclass:
BlackNWhite.h: a RGB->black / white operator -- yes, these are going to be graphics plugs, and disregard the types for the in / out buffers.. they are merely placeholders at this point.
#ifdef BLACKNWHITE_EXPORTS
#define BLACKNWHITE_API __declspec(dllexport)
#else
#define BLACKNWHITE_API __declspec(dllimport)
#endif
// This class is exported from the BlackNWhite.dll
class BLACKNWHITE_API CBlackNWhite : PCOperatorBase
{
public:
static PCOperatorBase::OperatorInfo* operatorInfo;
CBlackNWhite(void);
virtual ~CBlackNWhite(void);
//virtual int process(int* inBuffer, int* outBuffer, int bufferSize);
};
BLACKNWHITE_API CBlackNWhite* getOperatorInstance();
BLACKNWHITE_API const PCOperatorBase::OperatorInfo* getOperatorInfo();
And here the implementation file:
BlackNWhite.cpp:
#include "stdafx.h"
#include "BlackNWhite.h"
BLACKNWHITE_API CBlackNWhite* getOperatorInstance()
{
return new CBlackNWhite();
}
BLACKNWHITE_API const PCOperatorBase::OperatorInfo* getOperatorInfo()
{
return CBlackNWhite::operatorInfo;
}
CBlackNWhite::CBlackNWhite()
{
}
CBlackNWhite::~CBlackNWhite()
{
}
Now, I've tried a few approaches but I can't get the DLL to compile, because of the static member.The linker throws:
\BlackNWhite.lib and object c:\Projects\BlackNWhite\Debug\BlackNWhite.exp
1>BlackNWhite.obj : error LNK2001: unresolved external symbol "public: static struct PCOperatorBase::OperatorInfo * CBlackNWhite::operatorInfo" (?operatorInfo#CBlackNWhite##2PAUOperatorInfo#PCOperatorBase##A)
1>c:\Projects\BlackNWhite\Debug\BlackNWhite.dll : fatal error LNK1120: 1 unresolved externals
I thought that since the struct is defined inside the base class and the base class is exporting, the struct would export too. But I guess I'm wrong?
So how should I be doing it?
And regardless, is there a better approach to having the plugs' factory export their name,type and subtype without the need for instantiation than a static class member? For example, a resource file? or even another extern "C" function could return this info.. But I just felt that since it's C++ it makes the most sense to encapsulate this data (which is about the class as a factory itself) within the class, whether through a member or a method.
It doesn't have anything to do with DLLs, you declared the static member but you forgot to define it. Add this line to BlackNWhite.cpp:
PCOperatorBase::OperatorInfo* CBlackNWhite::operatorInfo = NULL;

Errors with a movieClip class

I have defined a class as
package telmate.com.audioB.volume {
import flash.display.MovieClip;
public class Volume_Bar extends MovieClip {
public static const BAR_WIDTH = 20;
public function Volume_Bar(op: Number, vol: Number) {
alpha = Util.clamp(op);
volume = vol;
}
private _volume:Number;// do we even need to store this?
public function set volume(v: Number){
_volume = v;
var f:uint = Util.clamp(v * totalFrames, 0, totalFrames - 1) + 1;
gotoAndStop(f);
}
}
}
and I am getting two errors: I am calling the constant BAR_WIDTH and instantiating it with parameters - new Volume_Bar(op, vol) -- and getting
/Users/dave/Documents/Audio/telmate/com/audioB/Audio_Bars.as, Line 152
1136: Incorrect number of arguments. Expected 0.
and
/Users/dave/Documents/Audio/telmate/com/audioB/Audio_Bars.as, Line 156
1119: Access of possibly undefined property BAR_WIDTH through a
reference with static type Class.
Why would this be?
Unfortunately, I don't know how specific I can be here, but...
That first error message indicates that when you're calling a function, you're passing arguments, but the function is not set up to handle arguments. Have you adjusted either the function itself, or the line of code that is calling it? (If you're calling through an event listener, be sure to include an argument in the function to hold the referring event. See documentation.)
What specifically is on Audio_bars.as, Line 152? That's where the error is occurring.
The second error seems to indicate that you haven't declared a function/variable by the name of "BAR_WIDTH". In reading your code, there doesn't appear to be an error in the declaration. Thus, you may be having a weird issue I've had before.
Hope that helps!