我正在编写一个 C++ 程序来与多个设备进行通信——一个带有 ATmega328 的 Arduino Pro Mini 和一个带有 GPS 屏蔽的 Arduino Uno——同时通过 COM 端口,我正在使用 boost::asio 包。我不是 C++ 大师,所以我偶尔会搞不清楚在哪里/何时通过引用或值传递;我认为这是其中一种情况。
这是设置用于通信的串行端口的代码
std::string IMU_COM_PORT = "COM5"; // or whatever... it varies
int IMU_BAUD_RATE = 57600;
std::string ARDUINO_COM_PORT = "COM3"; // also varies
int ARDUINO_BAUD_RATE = 115200;
int main() {
std::vector<boost::thread *> sensorThreads;
int sensorThreadCount = 0;
using namespace::boost::asio;
// get the COM port handle for the IMU sensor
boost::asio::io_service IMU_io;
boost::asio::serial_port IMU_port(IMU_io);
IMU_port.open(IMU_COM_PORT);
if (!IMU_port.is_open()) {
cerr << "Failed to connect to IMU." << endl;
}
else {
IMU_port.set_option(boost::asio::serial_port_base::baud_rate(IMU_BAUD_RATE));
// the IMU has to be put into triggered output mode with a specific command: #o0
// to put it back into continuous output mode we can use this command: #o1
std::string IMU_init_cmd = "#o0";
boost::asio::write(IMU_port, boost::asio::buffer(IMU_init_cmd.c_str(), IMU_init_cmd.size()));
// now the IMU should be ready
sensorThreads.push_back(new boost::thread(testIMUThread, IMU_port));
sensorThreadCount++;
}
// get the COM port handle for the ARDUINO board with GPS sensor
boost::asio::io_service ARDUINO_io;
boost::asio::serial_port ARDUINO_port(ARDUINO_io);
ARDUINO_port.open(ARDUINO_COM_PORT);
if (!ARDUINO_port.is_open()) {
cerr << "Failed to connect to ARDUINO." << endl;
}
else {
ARDUINO_port.set_option(boost::asio::serial_port_base::baud_rate(ARDUINO_BAUD_RATE));
// now the ARDUINO w/GPS sensor should be ready
sensorThreads.push_back(new boost::thread(testGPSThread, ARDUINO_port));
sensorThreadCount++;
}
for (int i = 0; i < sensorThreadCount; i++) {
sensorThreads[i]->join();
delete sensorThreads[i];
}
}
我的两个测试线程函数基本相同,唯一的区别是它们发送到设备的字节表明某些东西(我的计算机)正在等待从它们读取数据。
void testIMUThread(boost::asio::serial_port *port) {
while(true) { cout << readCOMLine(port, "#f") << endl; }
}
void testGPSThread(boost::asio::serial_port *port) {
while(true) { cout << readCOMLine(port, "r") << endl; }
}
并且这两个测试线程都使用一个执行串行读/写的函数。
std::string readCOMLine(boost::asio::serial_port *port, std::string requestDataCmd) {
char c;
std::string s;
boost::asio::write(port, boost::asio::buffer(requestDataCmd.c_str(), requestDataCmd.size()));
while(true) {
boost::asio::read(port, boost::asio::buffer(&c,1));
switch(c) {
case '\r': break;
case '\n': return s;
default: s += c;
}
}
}
上面的代码不会编译,而是产生以下内容(在 MSVC2010 中):
Error 11 error C2248: 'boost::asio::basic_io_object<IoObjectService>::basic_io_object' : cannot access private member declared in class 'boost::asio::basic_io_object<IoObjectService>' C:\boost_1_51_0\boost\asio\basic_serial_port.hpp
错误消息是相当无用的 - 至少对我来说 - 因为我无法找到根本原因。我在这里想念什么?
谢谢你的帮助。
编辑:解决方案(感谢 Sam Miller)
使用传递引用(即boost::ref()
)
sensorThreads.push_back(new boost::thread(testIMUThread, IMU_port));
sensorThreads.push_back(new boost::thread(testIMUThread, ARDUINO_port));
在main()
成为
sensorThreads.push_back(new boost::thread(testIMUThread, boost::ref(IMU_port)));
sensorThreads.push_back(new boost::thread(testIMUThread, boost::ref(ARDUINO_port)));
然后主力和线程函数被修改为这样
std::string readCOMLine(boost::asio::serial_port &port, std::string requestDataCmd) {
char c;
std::string s;
boost::asio::write(port, boost::asio::buffer(requestDataCmd.c_str(), requestDataCmd.size()));
while(true) {
boost::asio::read(port, boost::asio::buffer(&c,1));
switch(c) {
case '\r': break;
case '\n': return s;
default: s += c;
}
}
}
void testIMUThread(boost::asio::serial_port &port) {
while(true) { cout << readCOMLine(port, "#f") << endl; }
}
void testGPSThread(boost::asio::serial_port &port) {
while(true) { cout << readCOMLine(port, "r") << endl; }
}
另一方面,如果使用 pass-by-pointer,线程初始化main()
看起来像这样
sensorThreads.push_back(new boost::thread(testIMUThread, &IMU_port));
sensorThreads.push_back(new boost::thread(testIMUThread, &ARDUINO_port));
和这样的线程功能
void testIMUThread(boost::asio::serial_port *port) {
while(true) { cout << readCOMLine(port, "#f") << endl; }
}
void testGPSThread(boost::asio::serial_port *port) {
while(true) { cout << readCOMLine(port, "r") << endl; }
}
但是我必须对完成所有工作的函数(即读/写调用)进行一些额外的更改(在修改输入参数的基础上)。
std::string readCOMLine(boost::asio::serial_port *port, std::string requestDataCmd) {
char c;
std::string s;
port->write_some(boost::asio::buffer(requestDataCmd.c_str(), requestDataCmd.size())); // this line
while(true) {
port->read_some(boost::asio::buffer(&c,1)); // and this line
switch(c) {
case '\r': break;
case '\n': return s;
default: s += c;
}
}
}
两种解决方案都可以编译并且似乎可以满足我的目的。
谢谢!