0

I am planning on using Boost Asio library for targeting serial ports. I am not entirely sure how to use it, however.

As I understand it, asio needs to be built. In theory there is a ham build... script? - that is already configured for use in this case. However, I do not seem to have the building .exe. Apparently it can be obtained by building Boost.Build. However, running that build script also failed.

I have run bootstrap.bat, it failed citing that it cannot find "cl". The build script is the same.

I feel the answer is simple, but I am not certain. I tried an answer I saw here, but that also failed.

EDIT:

Built, successfully as far as I know. As I understand it, asio is a header-only library, but system is not. My configuration is for multithreaded static debug. I, using a bit of trial and error, and a boost doc page, found one that builds my code. However, it throws exceptions, and I am not sure if it is somehow a library mismatch or bad build - as this is the first line of code that would rely on whether or not it linked - or if my code is just bad and boost works fine.

Here is the code:

//SimpleSerial.h

#include <boost/asio.hpp>

class SimpleSerial
{
public:
    /**
     * Constructor.
     * \param port device name, example "/dev/ttyUSB0" or "COM4"
     * \param baud_rate communication speed, example 9600 or 115200
     * \throws boost::system::system_error if cannot open the
     * serial device
     */
    SimpleSerial(std::string port, unsigned int baud_rate)
    : io(), serial(io,port)
    {
        serial.set_option(boost::asio::serial_port_base::baud_rate(baud_rate));
    }

    /**
     * Write a string to the serial device.
     * \param s string to write
     * \throws boost::system::system_error on failure
     */
    void writeString(std::string s)
    {
        boost::asio::write(serial,boost::asio::buffer(s.c_str(),s.size()));
    }

    /**
     * Blocks until a line is received from the serial device.
     * Eventual '\n' or '\r\n' characters at the end of the string are removed.
     * \return a string containing the received line
     * \throws boost::system::system_error on failure
     */
    std::string readLine()
    {
        //Reading data char by char, code is optimized for simplicity, not speed
        using namespace boost;
        char c;
        std::string result;
        for(;;)
        {
            asio::read(serial,asio::buffer(&c,1));
            switch(c)
            {
                case '\r':
                    break;
                case '\n':
                    return result;
                default:
                    result+=c;
            }
        }
    }

private:
    boost::asio::io_service io;
    boost::asio::serial_port serial;
};


//end SimpleSerial.h

//main.cpp

#include <iostream>
#include "SimpleSerial.h"

using namespace std;
using namespace boost;

int main(int argc, char* argv[])
{


    try {

        SimpleSerial serial("COM1",115200);

        serial.writeString("Hello world\n");

        cout<<serial.readLine()<<endl;

    } catch(boost::system::system_error& e)
    {
        cout<<"Error: "<<e.what()<<endl;
        return 1;
    }
}

//end main.cpp

Exception throw on the SimpleSerial serial("COM1",115200); line. Error:

boost::exception_detail::clone_impl > at memory location 0x006DF470.

  • Asio is header only, though typically you need to link to the boost_system and boost_thread libraries. Have you installed boost? What platform are you using? – Sam Miller Apr 27 '13 at 13:52
  • In general, you don't want your `io_service` to be a sibling of the communication objects that it manages. I would suggest moving the `io_service` out from a member variable of the class `SimpleSerial`, and pass it in to the constructor. – Chad Apr 28 '13 at 03:04
  • The code was taken from the link in mkaes comments. I do not know much about it. If I were to use this, it would be a small project, and I doubt abstracted at all. –  Apr 28 '13 at 12:33
  • You don't provide the full exception wording. Anyway, some `serial_port` member functions might throw an exception on failure. Please see asio reference pages http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/reference/basic_serial_port/set_option/overload1.html – Igor R. Apr 30 '13 at 11:14

2 Answers2

3
  1. Linking

    Be sure to link to boost_system (for the error subsystem). Also, make doubly sure the .dll found at runtime exactly matches the .lib file used when building.

  2. Logging

    I suggest you add more exception detail:
    
    #include <boost/exception/diagnostic_information.hpp> 
    // ....
    
        } catch(boost::system::system_error& e)
        {
            cout<<"Error: " << e.what()<<endl;
            cout<<"Info: "  << boost::diagnostic_information(e) <<endl;
            return 1;
        }
    

    This would (on linux) print for "COM1:":

    Error: open: No such file or directory
    Info: Throw location unknown (consider using BOOST_THROW_EXCEPTION)
    Dynamic exception type: boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >
    std::exception::what: open: No such file or directory
    

    when run as root, or, when run as non-root for "/dev/tty0":

    Error: open: Permission denied
    Info: Throw location unknown (consider using BOOST_THROW_EXCEPTION)
    Dynamic exception type: boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >
    std::exception::what: open: Permission denied
    

    (of course, as root it runs without error for /dev/tty0).

sehe
  • 374,641
  • 47
  • 450
  • 633
  • Added this. Got about the same error as the top, although the wording was "could not find specified file" instead. Running as admin yields the same result. –  Apr 28 '13 at 23:20
0

You don't give us much information, but because of cl I assume you are running under windows.

So first you need a shell with you compiler in the path. Use the Visual Studio command prompt. Check that you can call cl on the prompt.

Second follow the build instruction. It should be as simple as described in chapter 5.3.1. At least it was when I tried to build boost under windows.

mkaes
  • 13,781
  • 10
  • 52
  • 72
  • Yes, I am on windows. I followed what you suggested, and... it seemed to go well - built for 40-some minutes. However, using some asio code, I get this: boost::exception_detail::clone_impl > at memory location 0x0021EE38. I don't know what that means. This was after trying several libraries (whether or not debug, how runtime is linked, etc) and this was the first that actually built. I don't know what the error means. –  Apr 27 '13 at 01:43
  • @Pawnguy7: So I assume you got the libraries you wanted. You build a program and it crashes when you execute it. Sounds like an error in your program or linking of wrong libraries. But this is difficult to say. – mkaes Apr 27 '13 at 09:36
  • It might be a library mismatch, but I am unsure. I oddly could not seem to find any good test code. Anyway, I was trying to open and write to a serial port. The call to port.open (the first possible linking errors) is where it is thrown. Near where it breaks is this, though, which seem to be to be related to... not the code, but architecture or a mismatch.Note I am only linking a form of the system library. On failed earlier mistmatches, it told me I had multithreading static debug. #if defined(_M_X64) && defined(_NTSUBSET_) Otherwise, I couldn't find proper code to test that I know is good. –  Apr 27 '13 at 12:33
  • All I can provide is this link. http://www.webalice.it/fede.tft/serial_port/serial_port.html. At least those example worked for me. – mkaes Apr 27 '13 at 14:07
  • Looked at that, tried it, still having issue. I edited the question. –  Apr 27 '13 at 22:32