I recently spent some time writing my first small application on Linux (Ubuntu 10.10 using GCC 4.5 and the Boost libraries). The plan is to try writing some cross-platform, portable C++, while trying out the new C++0x features that have been implemented in GCC 4.5.
This application uses the asio (asynchronous I/O) features in the Boost libraries along with the Boost serial_port implementation to read and display input from a serial port (e.g. GPS NMEA data). I also used experimental C++0x threading libraries and lambdas and tried the Boost implementation of the observer pattern - sockets and signals. I have yet to test this code on any other platform.
main.cpp
#include "headers.h"
#include "SerialPort.h"
using namespace std;
using namespace boost::asio;
int main()
{
//allow inter-mixing of wcout and cout calls (apparently non-standard)
ios::sync_with_stdio(false);
string portName = "/dev/ttyUSB1";
io_service ioService;
io_service::work work(ioService);
thread ioThread([&ioService] () { ioService.run(); });
SerialPort port(portName, 4800, ioService);
port.LineReceived.connect([] (std::vector<char> const & line)
{
cout << &line[0] << endl;
});
wcout << L"Listening on port: " << endl;
cout << portName << endl;
wcout << L"Press enter to stop listening..." << endl;
wstring result;
getline(wcin, result);
wcout << L"Exiting..." << endl;
ioService.stop();
ioThread.join();
}
headers.h
Separated for precompilation.
#include <boost/asio.hpp>
#include <boost/signal.hpp>
#include <iostream>
#include <vector>
#include <thread>
#include <functional>
SerialPort.h
#ifndef SERIALPORT_H
#define SERIALPORT_H
class SerialPort
{
public:
SerialPort(std::string const & portName, int portSpeed, boost::asio::io_service & ioService);
boost::signal<void(std::vector<char> const &)> LineReceived;
private:
void OnBytesRead(boost::system::error_code const &error, size_t bytesReceived);
void BeginListening();
std::vector<char> _readBuffer;
std::vector<char> _currentLine;
boost::asio::serial_port _port;
};
#endif // SERIALPORT_H
SerialPort.cpp
#include "headers.h"
#include "SerialPort.h"
using namespace std;
using namespace boost::asio;
SerialPort::SerialPort(string const & portName, int const portSpeed, io_service & ioService)
: _readBuffer(1000),
_port(ioService, portName)
{
_port.set_option(serial_port_base::baud_rate(portSpeed));
BeginListening();
}
void SerialPort::BeginListening()
{
_port.async_read_some(buffer(&_readBuffer[0], _readBuffer.size()),
[this](boost::system::error_code const &error, size_t bytesReceived)
{
this->OnBytesRead(error, bytesReceived);
});
}
void SerialPort::OnBytesRead(boost::system::error_code const &error, size_t bytesReceived)
{
if(error)
{
return;
}
for(size_t i = 0; i != bytesReceived; ++i)
{
char currentChar = _readBuffer[i];
switch(currentChar)
{
case '\r':
break;
case '\n':
LineReceived(_currentLine);
_currentLine.clear();
break;
default:
_currentLine.push_back(currentChar);
}
}
BeginListening();
}