I'm developing a control c++ library that needs to expose controller::open() function. However inside this function I have to call to the POSIX::open() function to open a file descriptor. The compiler complains I send Invalid Arguments to the controller function and doesn't understand I would like to call to the POSIX open() file function.
This is my code:
class declaration:
class PosixReadController {
int open();
}
implementation:
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
int PosixReadController::open()
{
int fd = open("/dev/ttyf1", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
/*
* Could not open the port.
*/
perror("open_port: Unable to open /dev/ttyf1 - ");
}
else
fcntl(fd, F_SETFL, 0);
return fd;
}
Error message (eclipse):
Invalid Arguments: 'Candidates are: int open()'
Changing the call to open to the global namespace with ::open doesn't help. Because I see the library already contains open function and I get the following error:
Invalid Arguments: 'Candidates are: int open(const char*, int, ...)
ImageCtrl* open(image) ''
Any idea?
Invalid Arguments: 'Candidates are: int open(char*, int, ...)
This is extremely suspicious. From where did you get this declaration of open? Did you include <fcntl.h>?
The prototype should actually look like this:
int open(const char *, int, ...);
const char * would have matched the string literal you passed, but char * obviously does not because a string literal is not writable.
Related
I'm trying to wrap arduino's RF24 functions into a simpler class that I could use more intuitively in the future, so I have made a .h file:
#ifndef RADIO_H
#define RADIO_H
#include <RF24.h>
#include <Arduino.h>
class Radio
{
private:
RF24 radio(int ce, int csn);
int opMode;
byte address;
protected:
void setReceiver();
void setTransmitter();
public:
Radio(int ce, int csn, int mode, byte channel);
};
#endif
and a .cpp file:
#include "Radio.h"
#include "Parameters.h"
#include <Arduino.h>
#include <SPI.h>
#include <RF24.h>
#include <nRF24L01.h>
Radio::Radio(int ce, int csn, int mode, byte channel){
RF24 radio(ce,csn);
radio.begin();
opMode = mode;
address = channel;
if(opMode == RX){
setReceiver();
}
else if(opMode == TX){
setTransmitter();
}
}
//Protected Functions
void Radio::setReceiver(){
//radio.openReadingPipe(0,address);
//radio.startListening();
}
void Radio::setTransmitter(){
//radio.openWritingPipe(address);
radio.stopListening();
}
However, I'm receiving the following error and can't figure out what's wrong with the code:
sketch\Radio.cpp: In member function 'void Radio::setTransmitter()':
Radio.cpp:74:2: error: invalid use of member function 'RF24
Radio::radio(int, int)' (did you forget the '()' ?)
radio.stopListening(); ^~~~~ Radio.cpp:74:2: error: invalid use of
member function 'RF24 Radio::radio(int, int)' (did you forget the '()'
?) exit status 1 invalid use of member function 'RF24
Radio::radio(int, int)' (did you forget the '()' ?)
can anyone help me figure out what went wrong?
You want an instance of RF24 called radio but you've declared a function called radio that returns an RF24 instance:
class Radio
{
private:
RF24 radio; // remove: (int ce, int csn);
...
Then in your constructor, initialize it like this:
Radio::Radio(int ce, int csn, int mode, byte channel)
: // colon starts the member initializer list
radio(ce, csn) // initialize the radio
{
...
You've declared a member function radio that takes two ints and returns a RF24.
Declare radio as a member variable in the same way as other member variables,
RF24 radio;
and initialize it in the initializer list,
Radio::Radio(int ce, int csn, int mode, byte channel)
: radio(ce, csn)
{
radio.begin();
// ...
I'm trying to compile my test group project but I have no success since the next compiling error that I can not understand in output:
Console output:
"test_TestHW.c: In member function ‘virtual void TEST_TestHW_TestHW_main_Test::testBody()’:
test_TestHW.c:617:6: error: request for member ‘enable’ in ‘mock’, which is
of non-class type ‘MockSupport&(const SimpleString&, MockFailureReporter*)’
mock.enable();
^
test_TestHW.c:651:6: error: request for member ‘disable’ in ‘mock’, which is of non-class
type ‘MockSupport&(const SimpleString&, MockFailureReporter*)’
mock.disable();"
Part of project codes:
Test group code .c file.
/*******************************************************************************
* INCLUDES
*******************************************************************************/
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness.h>
#include <CppUTestExt/MockSupport.h>
extern "C"
{
#include "RFID_Drv.h"
#include "HAL_AS393x_mock.h"
}
TEST_GROUP (TestHW)
{
protected:
public:
/* Define data accessible to test group members here */
void setup()
{
mock().disable();
}
void teardown()
{
/* Clean up steps are executed after each TEST */
mock().checkExpectations();
mock().clear();
}
};
TEST(TestHW,TestHW_main_FC_cuenta)
{
unsigned char error_val;
FLAG_Ocupado =0;
ControlEmi = 150; /* Valor de frecuencia para probar */
mock.enable();
mock().expectOneCall("CapturaTimer").andReturnValue(1000);
error_val=TestHW();
CHECK_EQUAL(error_val,FCENTRAL_CUENTA) /* Entra en el esatdo 2 */
CHECK_EQUAL(ControlEmi, 150);
mock.disable();
}
.......
//more test cases here
.......
int main(int ac, char** av)
{
/* Executes all the tests */
CommandLineTestRunner::RunAllTests(ac,av);
/* Returns value */
return(0);
}
Includes in mock.c file:
/*******************************************************************************
* INCLUDES
*******************************************************************************/
#include <CppUTest/TestHarness.h>
#include <CppUTestExt/MockSupport.h>
extern "C"
{
#include "timer_mock.h"
}
unsigned long CapturaTimer(void)
{
mock().actualCall("CapturaTimer");
return mock().unsignedIntReturnValue();
}
It seems that enable/disable are not considered and unknown by cpputest. I think it could be a silly thing that I've missed. But now I'm unable to see what one.
I know I'm testing C sources functions within a Cpp test file. Due this I was using extern c instance. I'm surprised because dis/en are not recognized but Mock().expectonecall is recognized (no compiling error).
Hence, will be there another way to en/disable mocks at the present
case?
Can it be seen some error in the way of including cpputest related
dependencies, etc? and if it possible how to fix them?
I have found the cause of this error:
I forgot "()" in:
mock.enable();
It must be replaced with:
mock().enable();
So it compiles.
I'm making a c++ serial class in Linux. I'm trying to register an event when incoming data is received.
I'm working on a Olimex Lime2 board.
gcc version 4.6.3 (Debian 4.6.3-14)
This is the error i get when trying to compile.
conSerial.cpp: In function ‘void signal_handler_IO(int)’:
conSerial.cpp:15:6: error: ‘EventHandler’ was not declared in this scope
I think this means that it doesn't have access to the class. Perhaps I've gone about this the wrong way. Any advice would be appreciated.
Thank you,
Steve
Header File
#ifndef CONSERIAL_H_
#define CONSERIAL_H_
#include "termios.h"
#include <sys/signal.h>
class conSerialEvents
{
public:
virtual void onReceive();
};
class conSerial
{
public:
conSerial(const char *port_, termios *options_, conSerialEvents *EventHandler_);
conSerial(const char *port_, termios *options_);
int open_port(void);
int send(const char *s, size_t len);
void close_port( void );
private:
conSerialEvents *EventHandler;
static const int PORT_OPEN = 0;
termios *options;
const char *port;
int fd;
struct sigaction saio;
};
#endif
Class File
#include <stdio.h> //Standard input/output definitions
#include <string.h> //String function definitions
#include <unistd.h> //UNIX standard function definitions
#include <fcntl.h> //File control definitions
#include <errno.h> //Error number definitions
#include <termios.h> //POSIX terminal control definitions
#include <iostream> //Input-Output Streams
#include "conSerial.h" //Header for this file
using namespace std;
void signal_handler_IO (int status);
void signal_handler_IO (int status)
{
std::cout << "Signal" << std::endl;
//This section fails because it can't see the class I think.
if (EventHandler)
{
EventHandler->onReceive();
}
//End this section
}
conSerial::conSerial(const char *port_, termios *options_)
{
this->EventHandler = 0L;
const char *port;
termios *options;
fd = -1;
}
conSerial::conSerial(const char *port_, termios *options_, conSerialEvents *EventHandler_)
{
this->EventHandler = EventHandler_;
const char *port;
termios *options;
fd = -1;
}
int conSerial::open_port(void){
struct termios options;
fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1){
//Could not open the port.
std::cout << "Port Failed to Open";
}else{
saio.sa_handler = signal_handler_IO;
sigemptyset(&saio.sa_mask);
saio.sa_flags = 0;
saio.sa_flags = SA_NODEFER;
saio.sa_restorer = NULL;
sigaction(SIGIO,&saio,NULL);
fcntl(fd, F_SETOWN, getpid());
fcntl(fd, F_SETFL, FNDELAY); // Sets the read() function to return NOW and not wait for data to enter buffer if there isn't anything there.
//Configure port for 8N1 transmission
tcgetattr(fd, &options); //Gets the current options for the port
cfsetispeed(&options, B38400); //Sets the Input Baud Rate
cfsetospeed(&options, B38400); //Sets the Output Baud Rate
options.c_cflag |= (CLOCAL | CREAD); //? all these set options for 8N1 serial operations
options.c_cflag |= PARENB; //?
options.c_cflag &= ~CSTOPB; //?
options.c_cflag &= ~CSIZE; //?
options.c_cflag |= CS7; //?
tcsetattr(fd, TCSANOW, &options); //Set the new options for the port "NOW"
std::cout << "seems like everything is ok, keep going\n";
};
return (fd);
};
int conSerial::send(const char *s, size_t len){
int written;
written = 0;
if (fd==-1){ //
// If this is -1 it means that the port is not open.
std::cout << "The port is not open." << std::endl;
}else{
// The port is open
tcdrain(fd);
written = write(fd, s, len);
}
return written;
}
void conSerial::close_port( void ){
if (fd !=-1){
close(fd);
}
}
In your "Class File", you declared a function:
void signal_handler_IO (int status)
which refers to some object called "EventHandler".
No such object is declared anywhere, hence the compilation error. It's as simple as that.
It is true that you declared a class named "conSerial", which happens to have a class member called "EventHandler".
However, that's a class right there. And a class member. The fact that you have some class that happens to declare a class member of the same name makes absolutely no difference, whatsoever. C++ doesn't work this way. signal_handler_IO is not a method in the same class. It is not even a static class function in that class. To access a class member you need one of two things: either an instance of a class, somewhere, in order to access its member; or access it from a non-static method in the same class, which automatically access the corresponding member of whatever class instance whose method it is. That's how C++ works.
And that's the fundamental explanation for your compilation error.
It is true that in a different class method called "open_port", you take a pointer to this signal_handler_IO function, and install it as a signal handler for SIGIO. Again, that doesn't really change anything.
It appears that you intend your conSerial class to be a singleton. In that case, the cleanest solution for your conundrum is:
Refactor the class so that it's construction and destruction uses the singleton design pattern, as much as possible.
Install the signal handler in the class's constructor, and uninstall the signal handler in its destructor.
Have the constructor save a pointer to this in a private static class member, before installing the signal handler.
Move the bulk of signal_handler_IO into a static class method, and have signal_handler_IO do nothing except invoke the static class method.
Have you static class method use the pointer that was set up in step 3 access the actual instance of your singleton class. Now, it can do whatever it wants to do with its "EventHandler" class member.
What I want to achieve: I want to set custom baud rate values for some tty*-like UART-mapped terminals.
How: The only way I found by far is to use the struct termios2 structure which is located in<asm/termios> header (as mentioned here, first answer).
My solution works very well by far, but now I need to use some functions:
speed_t cfgetispeed(const struct termios *);
int tcdrain(int);
int tcflow(int, int);
int tcflush(int, int);
int tcgetattr(int, struct termios *);
pid_t tcgetsid(int);
int tcsendbreak(int, int);
int tcsetattr(int, int, struct termios *);
The problem is that in <asm/termios.h> there are no such functions, and I need to include <termios.h> for being able to use them.
Problem: If I include both headers (<asm/termios.h> and <termios.h>) the compiler will scream about functions and structure re-declaration, and he's right.
How can I solve this without using some obscure practice (like wrapping one of headers in a namespace, like mentioned here)?
How can I solve this without using some obscure practice (like wrapping one of headers in a namespace, like mentioned here)?
If you find namespaces obscure, I don't know how you'd call this:
#define termios asmtermios
#include <asm/termios.h>
#undef termios
#include <termios.h>
Anyway, this too gets you rid of the error: redefinition of 'struct termios'.
I had a similar issue - wanted custom baud rate support with definitions like termios2, TCGETS2 and BOTHER, while still making use of the traditional termios calls. I instinctively wrapped the termios2 stuff in its own compilation unit and had no problems. So my structure looks like this:
serial_driver.c/.h
#include <termios.h>
#include <fcntl.h>
#include <dirent.h>
int open_port(int fd, int baudrate, eParitySetting parity, int numStopBits)
{
if(baudrate_is_non_standard(baudrate)
setNonStandardBaudRateTermios(fd, baudrate, parity, numStopBits);
else
//all the normal tcgetattr/cfsetospeed/tcsetattr
}
int do_other_things(void)
{
//all the normal tcsendbreak/tcflush/etc things
}
serial_driver_abr.c/.h
#include <asm/termios.h> /* asm gives us the all important BOTHER and TCGETS2 */
#include <fcntl.h>
#include <dirent.h>
#include <stropts.h> /* Oddly, for ioctl, because ioctl.h causes include dramas */
setNonStandardBaudRateTermios(int fd, int baudrate, eParitySetting parity, int numStopBits)
{
//All the termios2/ioctl/TCGETS2/BOTHER things
}
Works well for me.
I hit the same problem with an old arm cross compiler, but found the latest one, gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf, solved the problem with a different header file. Here is my code:
[uart_config.c]
#include <asm/termbits.h>
#include <sys/ioctl.h>
/* functions */
int uart_config_baudrate(int fd)
{
struct termios2 tio;
ioctl(fd, TCGETS2, &tio);
tio.c_cflag &= ~CBAUD;
tio.c_cflag |= BOTHER;
tio.c_ispeed = MY_SPECIAL_BAUDRATE_NUMBER;
tio.c_ospeed = MY_SPECIAL_BAUDRATE_NUMBER;
return ioctl(fd, TCSETS2, &tio);
}
[main.c]
static int init_uart(void)
{
struct termios tp;
int rc;
memset(&tp, 0, sizeof(tp));
tp.c_cflag = MY_SPECIAL_BAUDRATE | CS8 | CLOCAL | CREAD | PARENB | PARODD;
tp.c_iflag = IGNPAR;
tp.c_oflag = 0;
tp.c_lflag = 0; /* set input mode to non-canonical */
tp.c_cc[VTIME] = 0; /* inter-character timer unused */
tp.c_cc[VMIN] = 1; /* blocking read until 5 chars received */
tcflush(fd, TCIFLUSH);
rc = tcsetattr(fd, TCSANOW, &tp);
return rc;
}
int main()
{
int fd;
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY);
init_uart(fd); // add your error handling
uart_config_baudrate(fd); // add your error handling
...
}
I don't think any of these answer address the issue correctly (they are rather hacky). The sources of glibc gives you a good idea on how to implement those functions quite easily:
For exemple tcdrain is a simple ioctl call:
ioctl (fd, TCSBRK, 1)
I'm currently working on I2C between a Raspberry Pi 3 and a PsoC 4. I'm using the I2C-dev library to handle the I2C communication. So the I2C bus is up and running, and the read and write function has been implemented correctly. I want however to make functions pointer the read and write functions hence the to functions uses the same types of arguments (atleast it looks like) I have the following main code called I
2Ctest-tools.cpp:
#include <unistd.h> //Needed for I2C port
#include <fcntl.h> //Needed for I2C port
#include <sys/ioctl.h> //Needed for I2C port
#include <linux/i2c-dev.h> //Needed for I2C port
#include <stdio.h>
#include "i2c.h"
#include "functions.h"
int main() {
int addr = 0x49;
int cmd = 2; //Write
int length = 5;
int file_i2c = 0;
I2C myI2C;
unsigned char buffer[5];
buffer[0] = 0x01;
buffer[1] = 0x02;
buffer[2] = 0x20;
buffer[3] = 0x00;
buffer[4] = 0x17;
i2c_init(&myI2C, cmd, addr, &file_i2c);
i2c_exe(&myI2C, file_i2c, buffer, length);
return 0;
}
As shown in the code, im using a object of the struct called myI2C which is passed in the two functions i2c_init, i2c_exe. The source code for functions.cpp is in the following:
#include <unistd.h> //Needed for I2C port
#include <fcntl.h> //Needed for I2C port
#include <sys/ioctl.h> //Needed for I2C port
#include <linux/i2c-dev.h> //Needed for I2C port
#include <stdio.h>
#include "i2c.h"
#include "functions.h"
int i2c_init(I2C *cthis, int cmd, int addr, int *ptrFile_i2c ) {
char *filename = (char*)"/dev/i2c-1";
if ((*ptrFile_i2c = open(filename, O_RDWR)) < 0)
{
//ERROR HANDLING: you can check errno to see what went wrong
printf("Failed to open the i2c bus");
return 0;
}
if (ioctl(*ptrFile_i2c, I2C_SLAVE, addr) < 0)
{
printf("Failed to acquire bus access and/or talk to slave.\n");
//ERROR HANDLING; you can check errno to see what went wrong
return 0;
}
switch(cmd) {
case 1:
//cthis->WR = write;
break;
case 2:
cthis->WR = read;
break;
}
return 0;
}
int i2c_exe(I2C *cthis, int file_i2c, unsigned char *buffer, size_t length) {
cthis->WR(file_i2c, buffer, length);
return 0;
}
So the important thing to note here is that in the function i2c_init im switching on the varialbe cmd, which dictates whether the function pointer will point on the write or read function. Now the failure part comes in. The functions pointer is declared in its own .h file called i2c.h and looks like this:
struct I2C {
ssize_t (*WR)(int, const void *, size_t);
};
As you can see the function pointer has to point on a function with the parameters (int, const void*, size_t) this works like a charm when the function points on the write function BUT when it points on the read function im getting and error, the error says:
functions.cpp: In function ‘int i2c_init(I2C*, int, int, int*)’:
functions.cpp:30:14: error: invalid conversion from ‘ssize_t ()(int, void, size_t) {aka int ()(int, void, unsigned int)}’ to ‘ssize_t ()(int, const void, size_t) {aka int ()(int, const void, unsigned int)}’ [-fpermissive]
cthis->WR = read;
I have studied the error and concluded that it's because the read and write function somehow does not take the same arguments, which is weird because im passing the same arguments in them (int i2s_file, int buffer, int length) so if i change the function pointer to
ssize_t (*WR)(int, void *, size_t);
the function works with read but not with write.. So my question is: can i somehow change the write or read function to take the same argument by changing the i2c-dev library or is there anything else i could do to solve this problem?
here's a link to the i2c-dev library, which i have completely giving up to understand http://textuploader.com/5yioi
thanks in advanced
You can cast the functions explicitly to the correct type:
typedef ssize_t (*I2CCMD)(int, void *, size_t);
cthis->WR = (I2CCMD)write;
cthis->WR = (I2CCMD)read;
This should eliminate the error.
Obviously the read function cannot take a pointer to const since, unlike the write function, it has to modify that parameter.
So you cannot switch functionality with a function pointer, because the function pointers are of different types.
The best work-arounds seem to be either moving the "cmd" parameter to the i2c_exe function, or alternatively create a private variable containing cmd (inside struct I2C would be ideal). And then in i2c_exe either call read or write.
A worse solution is to change the struct to a union, like:
union I2C {
ssize_t (*WR)(int, const void *, size_t);
ssize_t (*read)(int, void*, size_t);
};
Then in case of reads, use the read member to assign to the struct. But please note that this is kind of a "dirty hack", it is poorly-specified behavior in theory. In practice, it will most likely work on any given system. (It is very unlikely that const correctness would ever affect calling convention.)