I would try to use the library to use socket Boost.Asio c++ on multiple platforms.
I downloaded the latest version here:
http://sourceforge.net/projects/boost/files/boost/1.46.1/
but now what do I use in my code?
I have compile it? include just enough?
Can you tell me the steps?
How you use it depends on what you want to do, ;-).
The documentation is found here:
http://www.boost.org/doc/libs/1_46_1/doc/html/boost_asio.html
You will find lots of examples that should suite your needs.
For building, you should note that the library dependancies depend upon whether you are running on windows or linux. See here
http://www.boost.org/doc/libs/1_46_1/doc/html/boost_asio/using.html
In particular:
With MSVC or Borland C++ you may want
to add -DBOOST_DATE_TIME_NO_LIB and
-DBOOST_REGEX_NO_LIB to your project settings to disable autolinking of the
Boost.Date_Time and Boost.Regex
libraries respectively. Alternatively,
you may choose to build these
libraries and link to them
If you don't want the dependancies to the other boost libraries then you can use the non-boost (i think otherwise identical asio) library from here: http://think-async.com/
For sources of other documentation see this question on SO: Best documentation for Boost:asio?
As an example, to open a serial port you might write something like this:
/** Manage serial connections.*/
class serial_manager
{
boost::asio::io_service m_io_service;
std::string m_name;
const unsigned int m_baud_rate;
const enum flow_control::type m_flow_control;
const enum parity::type m_parity;
const enum stop_bits::type m_stop_bits;
const unsigned int m_char_size;
boost::asio::serial_port m_SerialPort;
boost::system::error_code m_error;
public:
/** A constructor.
* #param name The dvice name, for example "COM1" (windows, or "/dev/ttyS0" (linux).
* #param baud_rate The baud rate.
* #param flow_control The flow control. Acceptable values are flow_control::none, flow_control::software, flow_control::hardware.
* #param parity The parity of the connection. Acceptable values are parity::none, parity::even, parity::odd.
* #param stop_bits The number of stop bits. Acceptable values are stop_bits::one, stop_bits::one_point_five, stop::bits::two
* #param char_size The number of characters in connection.
*/
serial_manager(const std::string& name,
const unsigned int& baud_rate = 19200,
const enum flow_control::type& flow_control = flow_control::none,
const enum parity::type& parity = parity::none,
const enum stop_bits::type& stop_bits = stop_bits::one,
const unsigned int& char_size = 8
)
;
void open();
};
void
serial_manager::open() {
if (!m_SerialPort.is_open())
{
m_SerialPort.open(m_name, m_error);
if (m_error == boost::system::errc::no_such_file_or_directory )
{ //for example you tried to open "COM1" on a linux machine.
//... handle the error somehow
}
m_SerialPort.set_option(boost::asio::serial_port::baud_rate(m_baud_rate));
m_SerialPort.set_option(boost::asio::serial_port::flow_control(m_flow_control));
m_SerialPort.set_option(boost::asio::serial_port::parity(m_parity));
m_SerialPort.set_option(boost::asio::serial_port::stop_bits(m_stop_bits));
m_SerialPort.set_option(boost::asio::serial_port::character_size(m_char_size));
}
}
Read through some of the previous Boost.Asio questions on SO. You will get a good idea about some of the techniques used when using this library.
Related
I am trying to tie together a few different libraries for a project I'm working on. The code is for a Teensy 4.1 in VS Code and PlatformIO
I am trying to use lvgl https://lvgl.io/ (graphics library) and ILI9341_t3n LCD libraries https://github.com/KurtE/ILI9341_t3n.
The ILI9341_t3n library has functions that use DMA to asynchronously update the display. I would like to use it as my display driver.
The ILI9341_t3n library uses a framebuffer and the pointer is pointing to a uint16_t.
However, the lvgl library does things a bit differently. It uses a _lv_disp_draw_buf_t struct to hold several more variables, like fb size, which buffer to use (if double buffer) and other status indicators.
typedef struct _lv_disp_draw_buf_t {
void * buf1; /**< First display buffer.*/
void * buf2; /**< Second display buffer.*/
/*Internal, used by the library*/
void * buf_act;
uint32_t size; /*In pixel count*/
/*1: flushing is in progress. (It can't be a bit field because when it's cleared from IRQ Read-Modify-Write issue might occur)*/
volatile int flushing;
/*1: It was the last chunk to flush. (It can't be a bit field because when it's cleared from IRQ Read-Modify-Write issue might occur)*/
volatile int flushing_last;
volatile uint32_t last_area : 1; /*1: the last area is being rendered*/
volatile uint32_t last_part : 1; /*1: the last part of the current area is being rendered*/
} lv_disp_draw_buf_t;
The code to create and initialize a buffer is as follows.
static _lv_disp_draw_buf_t draw_buf;
static lv_color_t buf_1[MY_DISP_HOR_RES * 10]; /*A screen sized buffer*/
static lv_color_t buf_2[MY_DISP_HOR_RES * 10]; /*Another screen sized buffer*/
lv_disp_draw_buf_init(&draw_buf, buf_1, buf_2, MY_DISP_HOR_RES * 10); /*Initialize
The init code is:
void lv_disp_draw_buf_init(lv_disp_draw_buf_t * draw_buf, void * buf1, void * buf2, uint32_t
size_in_px_cnt)
{
lv_memset_00(draw_buf, sizeof(uint16_t));
draw_buf->buf1 = buf1;
draw_buf->buf2 = buf2;
draw_buf->buf_act = draw_buf->buf1;
draw_buf->size = size_in_px_cnt;
}
The ILI9341_t3n code for initializing the frame buffer is much more simple.
void ILI9341_t3n::setFrameBuffer(uint16_t *frame_buffer) {
#ifdef ENABLE_ILI9341_FRAMEBUFFER
_pfbtft = frame_buffer;
_dma_state &= ~ILI9341_DMA_INIT; // clear that we init the dma chain as our
// buffer has changed...
#endif
}
I would like to create a framebuffer like the lvgl library recommends, and then pass it into this function. I can modify the code so that the LCD library can do something like:
_pfbtft = draw_buf->buf1;
//or//
_pfbtft = draw_buf->buf2;
That way, I can use lvgl to update the framebuffer, and use the ILI9341 library just for handling the DMA transactions.
The problem is I don't know how to incorporate the _lv_disp_draw_buf_t data type into the ILI9341 library. I tried changing the uint16_t to _lv_disp_draw_buf_t just to see what would happen and it says it's an undefined variable type.
Is this a somewhat trivial task or will it require rewriting a lot of code?
Or maybe I dont need to incorporate it. If I call:
tft.setFrameBuffer(&frame_buffer);
Is there a way I could access the framebuffer pointer contained in the _lv_disp_draw_buf_t data type and pass it instead?
If it's not a simple answer, please advise some topics that I should study so that I can learn how to do this.
It's possible I'm going about this all wrong, so constructive criticism is appreciated.
I did several google searches to see if this has been answered before, but my search terms are limited by my knowledge of the terminology, so if it has I apologize.
so I have been writing some code and finished it, all I had left to do was send it over SPI. However, I didn't realise that the SPI library I am using only accepts const uint_16t data. I tried setting up a temp variable of the correct data type and using a reference to send over SPI, which works, but because it is a const variable it cant change, which is something I need it to be able to do.
Below is my code, any help with this would be great, for reference this is done in C++ and uses SPI library is part of the Raspberry Pi Pico SDK (the code is cut down as is long so only needed parts included). I did try to use pointers to change the const variable which I think you can do in C but I couldn't get it to work in C++.
Any help with this would be greatly appreciated as I am very stuck as with how to go about fixing this.
Thanks,
Dean
class Frequency_Values{
Public:
static uint16_t position;
//constructors and special member functions here
private:
uint16_t MSB_LUT[401];
uint16_t LSB_LUT[401];
};
//----------static variable definition---------------------
unsigned short Frequency_Values::position = 0;
//---------------------------------------------------------
//-------------------get function definitions--------------
uint16_t Frequency_Values::get_MSB_LUT_Value()
{
return (Frequency_Values::MSB_LUT[position]);
}
uint16_t Frequency_Values::get_LSB_LUT_Value()
{
return (Frequency_Values::LSB_LUT[position]);
}
//-----------------------------------------------------------
Frequency_Values MSB, LSB;
int main(){
while(1){ // to show code runs multiple times
//--------------------------------------------------
const uint16_t LSB_Holder = LSB.get_LSB_LUT_Value(); // this is what I tried to get it in the correct data type
//which worked but as const the value wont change
const uint16_t MSB_Holder = MSB.get_MSB_LUT_Value();
//--------------------------------------------------
}
spi_write16_blocking(SPI_PORT, &LSB_Holder, 1);
spi_write16_blocking(SPI_PORT, &MSB_Holder, 1);
}
This was eventually fixed by just removing the const specifier inside of the pico sdk, spi library.
I want to create a new library which controls arduino's Serial library.
Here is what I want ...
main Sketch
#include <newLibrary.h>
newLibrary connection(2,9600); // 2 is Serial2, 9600 is baudRate
void main()
{
connection.start();
}
newLibrary.cpp
newLibrary::newLibrary (uint8_t port, long baudRate)
{
__port = port;
__baudRate = baudRate;
}
void newLibrary::start()
{
(Serial+port).begin(); // I need to add port to Serial to make Serial2
}
What I want to do is,
The user will choose which Serial port(eg. Serial/Serial1/Serial2 etc...) is going to be used with ;
newLibrary connection(2,9600); // 2 is Serial2, 9600 is baudRate
and after that the start function in newLibrary.h will start that Serial port with an algorithm like;
void newLibrary::start()
{
(Serial+port).begin(); // Which is equal to Serial.begin() or Serial1.begin() etc
}
I know it can be done by if statement or switch case...
But is there another way?
Such as macros....
I know that the macros can be used like ;
#define serialPort (Serial##1) // so the serialPort refers to Serial1
But this way doesnt work for me....
C++ doesn't support reflection. You can't build variable names at runtime.
You could store pointers to the objects in a container.
#include <array>
class S {
public:
void begin() {}
} Serial, Serial1, Serial2;
int main() {
std::array serials = {&Serial, &Serial1, &Serial2};
std::uint8_t port = 1;
serials[port]->begin();
}
Instead of taking a uint8_t why don't you take a Stream object and then you can pass Serial2 directly like: newLibrary connection(Serial2,9600);
newLibrary::newLibrary (Stream port, long baudRate)
{
__port = port;
__baudRate = baudRate;
}
newLibrary connection(Serial2,9600);
void newLibrary::start()
{
_port.begin(_baudRate); // Which is equal to Serial.begin() or Serial1.begin() etc
}
Of course you also need to change the line in the class definition that defines _port, but since you didn't post that bit I'll assume you know how to do that.
Moral of the story is, those serial ports are objects of type Stream, so you can pass them around just like variables as long as you use the type Stream instead of int or byte or char.
I'm looking to develop a set of C APIs that will wrap around our existing C++ APIs to access our core logic (written in object-oriented C++). This will essentially be a glue API that allows our C++ logic to be usable by other languages. What are some good tutorials, books, or best-practices that introduce the concepts involved in wrapping C around object-oriented C++?
This is not too hard to do by hand, but will depend on the size of your interface.
The cases where I've done it were to enable use of our C++ library from within pure C code, and thus SWIG was not much help. (Well maybe SWIG can be used to do this, but I'm no SWIG guru and it seemed non-trivial)
All we ended up doing was:
Every object is passed about in C an opaque handle.
Constructors and destructors are wrapped in pure functions
Member functions are pure functions.
Other builtins are mapped to C equivalents where possible.
So a class like this (C++ header)
class MyClass
{
public:
explicit MyClass( std::string & s );
~MyClass();
int doSomething( int j );
}
Would map to a C interface like this (C header):
struct HMyClass; // An opaque type that we'll use as a handle
typedef struct HMyClass HMyClass;
HMyClass * myStruct_create( const char * s );
void myStruct_destroy( HMyClass * v );
int myStruct_doSomething( HMyClass * v, int i );
The implementation of the interface would look like this (C++ source)
#include "MyClass.h"
extern "C"
{
HMyClass * myStruct_create( const char * s )
{
return reinterpret_cast<HMyClass*>( new MyClass( s ) );
}
void myStruct_destroy( HMyClass * v )
{
delete reinterpret_cast<MyClass*>(v);
}
int myStruct_doSomething( HMyClass * v, int i )
{
return reinterpret_cast<MyClass*>(v)->doSomething(i);
}
}
We derive our opaque handle from the original class to avoid needing any casting, and (This didn't seem to work with my current compiler). We have to make the handle a struct as C doesn't support classes.
So that gives us the basic C interface. If you want a more complete example showing one way that you can integrate exception handling, then you can try my code on github : https://gist.github.com/mikeando/5394166
The fun part is now ensuring that you get all the required C++ libraries linked into you larger library correctly. For gcc (or clang) that means just doing the final link stage using g++.
I think Michael Anderson's answer is on the right track but my approach would be different. You have to worry about one extra thing: Exceptions. Exceptions are not part of the C ABI so you cannot let Exceptions ever be thrown past the C++ code. So your header is going to look like this:
#ifdef __cplusplus
extern "C"
{
#endif
void * myStruct_create( const char * s );
void myStruct_destroy( void * v );
int myStruct_doSomething( void * v, int i );
#ifdef __cplusplus
}
#endif
And your wrapper's .cpp file will look like this:
void * myStruct_create( const char * s ) {
MyStruct * ms = NULL;
try { /* The constructor for std::string may throw */
ms = new MyStruct(s);
} catch (...) {}
return static_cast<void*>( ms );
}
void myStruct_destroy( void * v ) {
MyStruct * ms = static_cast<MyStruct*>(v);
delete ms;
}
int myStruct_doSomething( void * v, int i ) {
MyStruct * ms = static_cast<MyStruct*>(v);
int ret_value = -1; /* Assuming that a negative value means error */
try {
ret_value = ms->doSomething(i);
} catch (...) {}
return ret_value;
}
Even better: If you know that all you need as a single instance of MyStruct, don't take the risk of dealing with void pointers being passed to your API. Do something like this instead:
static MyStruct * _ms = NULL;
int myStruct_create( const char * s ) {
int ret_value = -1; /* error */
try { /* The constructor for std::string may throw */
_ms = new MyStruct(s);
ret_value = 0; /* success */
} catch (...) {}
return ret_value;
}
void myStruct_destroy() {
if (_ms != NULL) {
delete _ms;
}
}
int myStruct_doSomething( int i ) {
int ret_value = -1; /* Assuming that a negative value means error */
if (_ms != NULL) {
try {
ret_value = _ms->doSomething(i);
} catch (...) {}
}
return ret_value;
}
This API is a lot safer.
But, as Michael mentioned, linking may get pretty tricky.
Hope this helps
It is not hard to expose C++ code to C, just use the Facade design pattern
I am assuming your C++ code is built into a library, all you need to do is make one C module in your C++ library as a Facade to your library along with a pure C header file. The C module will call the relevant C++ functions
Once you do that your C applications and library will have full access to the C api you exposed.
for example, here is a sample Facade module
#include <libInterface.h>
#include <objectedOrientedCppStuff.h>
int doObjectOrientedStuff(int *arg1, int arg2, char *arg3) {
Object obj = ObjectFactory->makeCppObj(arg3); // doing object oriented stuff here
obj->doStuff(arg2);
return obj->doMoreStuff(arg1);
}
you then expose this C function as your API and you can use it freely as a C lib with out worrying about
// file name "libIntrface.h"
extern int doObjectOrientedStuff(int *, int, char*);
Obviously this is a contrived example but this is the easiest way to expos a C++ library to C
I would think you may be able to get some ideas on direction and/or possibly utilize directly SWIG. I would think that going over a few of the examples would at least give you an idea of what kinds of things to consider when wrapping one API into another. The exercise could be beneficial.
SWIG is a software development tool that connects programs written in C and C++ with a variety of high-level programming languages. SWIG is used with different types of languages including common scripting languages such as Perl, PHP, Python, Tcl and Ruby. The list of supported languages also includes non-scripting languages such as C#, Common Lisp (CLISP, Allegro CL, CFFI, UFFI), Java, Lua, Modula-3, OCAML, Octave and R. Also several interpreted and compiled Scheme implementations (Guile, MzScheme, Chicken) are supported. SWIG is most commonly used to create high-level interpreted or compiled programming environments, user interfaces, and as a tool for testing and prototyping C/C++ software. SWIG can also export its parse tree in the form of XML and Lisp s-expressions. SWIG may be freely used, distributed, and modified for commercial and non-commercial use.
Just replace the concept of an object with a void * (often referred to as an opaque type in C oriented libraries) and reuse everything you know from C++.
I think using SWIG is the best answer... not only it avoid reinventing wheel but it is reliable and also promote a continuity in development rather than one shooting the problem.
High frequency problems need to be addressed by a long term solution.
I am trying to compile cp210x USB-UART driver on Debian 7 and getting the following error (when make command):
/var/distr/sillabs/Linux_3.x.x_VCP_Driver_Source/cp210x.c:589:17: error: request for member ‘c_cflag’ in something not a structure or union
Here is a fragment of code, line 589 (starts with &tty->), cp210x.c:
static void cp210x_get_termios(struct tty_struct *tty,
struct usb_serial_port *port)
{
unsigned int baud;
if (tty) {
cp210x_get_termios_port(tty->driver_data,
&tty->termios.c_cflag, &baud);
tty_encode_baud_rate(tty, baud, baud);
} else {
unsigned int cflag;
cflag = 0;
cp210x_get_termios_port(port, &cflag, &baud);
}
}
I think something is wrong with the &tty->termios.c_cflag construction. Please help how to fix it?
Thank you!
It means that in your definition of tty_struct, termios is a structure pointer, not a structure. You need to change the expression
&tty->termios.c_cflag
to
&tty->termios->c_cflag
The definition of tty_struct changed between versions 2.x and 3.x of the Linux kernel.
The driver you're building expects it to contain:
struct ktermios termios, termios_locked;
from 3.x, but you are using the includes from 2.x:
struct ktermios *termios, *termios_locked;
You can either reconsider the kernel you're using to better meet the driver's requirements, or you can hack the driver's code yourself:
- &tty->termios.c_cflag
+ &tty->termios->c_cflag
I would also suggest talking to the driver developer about this, if the requirements are unclear.
a tty_struct contain, among other thing:
// from tty.h
struct tty_struct {
int magic;
// some cut
struct ktermios termios, termios_locked;
// more cut
};
a ktermios in turn, is defined like:
// from termbits.h
struct ktermios {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
and finally, a tcflag_t is:
// also from termbits.h
typedef unsigned int tcflag_t;
so, in conclusion, it should work.
What could muck up that? My first guess would be a macro.
Prime suspect would be that you have a termios macro.
If not that, don't look for the error at line where its reported, it's probably a side-effect of something else.
For example, do you have old headers that the compiler might find instead of those you want? If you are trying to compile a driver for v3 with headers from v2 it wont work.