[{"data":1,"prerenderedAt":5638},["ShallowReactive",2],{"wiki-page-/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch19-1-3-chuan-kou-tong-xin":3,"wiki-doc-items-/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch19-1-3-chuan-kou-tong-xin":5211,"language-switcher-data-/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch19-1-3-chuan-kou-tong-xin":5622,"wiki-i18n-paths-/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch19-1-3-chuan-kou-tong-xin":5637},{"id":4,"title":5,"body":6,"canonicalPath":5193,"chapter":5194,"chapterSort":5195,"date":5196,"description":26,"docI18nKey":5197,"docKey":5198,"docRoot":5199,"docTitle":5200,"extension":5201,"i18nKey":5202,"isBlogPost":5203,"isWikiDoc":245,"isWikiIndex":5203,"layout":5204,"legacyPath":5205,"locale":5206,"localeSlug":5207,"meta":5208,"navigation":245,"path":5193,"seo":5209,"sourcePath":5205,"sourceStem":5202,"stem":5202,"wikiDepth":71,"__hash__":5210},"content/wiki/2023-10-05-Cplusplus教学/ch19-1-3-串口通信.md","串口通信",{"type":7,"value":8,"toc":5141},"minimark",[9,16,19,30,37,40,45,52,57,60,86,89,105,108,111,137,140,146,149,155,166,168,176,179,185,191,197,200,943,950,953,956,976,979,992,995,1031,1034,1037,1043,1046,1051,1054,1057,1064,1067,1074,1077,1080,1089,1101,1110,1113,1119,1122,1128,1131,1134,1136,1143,1146,1152,1155,1639,1643,1646,1648,1668,1671,1701,1704,1722,1725,1728,1734,1737,1751,1754,1760,1763,1766,1772,1775,1778,1784,1789,1792,1799,1801,1808,1811,1814,1841,1844,2515,2519,2522,2524,2544,2546,2576,2579,2595,2598,2601,2607,2613,2619,2622,2628,2631,2636,2639,2653,2656,2659,2664,2699,2702,2729,2732,2744,2747,2749,2753,2756,2759,2762,2765,3706,3710,3713,3715,3735,3737,3767,3770,3808,3811,3814,3820,3823,3829,3835,3838,3841,3853,3860,3866,3869,3894,3901,3904,3907,3957,3960,3979,3981,3985,3988,3991,3997,4004,4010,4013,4906,4910,4913,4915,4935,4937,4947,4950,4980,4983,4986,4992,4994,4999,5002,5009,5012,5033,5036,5042,5062,5065,5068,5098,5103,5105,5108,5137],[10,11,12],"blockquote",{},[13,14,15],"p",{},"串口是机器人里最常见的通信方式之一：上位机 ROS2 / Linux 程序通过 USB-TTL、USB-CAN 转串口、CH340、CP2102、FT232 等设备和 STM32、ESP32、下位机控制板通信。",[13,17,18],{},"本节依旧遵循顺序：",[20,21,27],"pre",{"className":22,"code":24,"language":25,"meta":26},[23],"language-text","先写普通 main() 里的同步示例\n再写普通 main() 里的异步示例\n最后写类封装版本\n","text","",[28,29,24],"code",{"__ignoreMap":26},[13,31,32,33,36],{},"所有异步回调统一使用 ",[28,34,35],{},"std::bind","。",[38,39],"hr",{},[41,42,44],"h2",{"id":43},"linux-下准备虚拟串口测试环境","Linux 下准备虚拟串口测试环境",[13,46,47,48,51],{},"如果你手里没有真实 STM32，可以用 ",[28,49,50],{},"socat"," 创建一对虚拟串口。",[53,54,56],"h3",{"id":55},"安装-socat","安装 socat",[13,58,59],{},"Ubuntu / Debian：",[20,61,65],{"className":62,"code":63,"language":64,"meta":26,"style":26},"language-bash shiki shiki-themes github-light github-dark","sudo apt install socat\n","bash",[28,66,67],{"__ignoreMap":26},[68,69,72,76,80,83],"span",{"class":70,"line":71},"line",1,[68,73,75],{"class":74},"sScJk","sudo",[68,77,79],{"class":78},"sZZnC"," apt",[68,81,82],{"class":78}," install",[68,84,85],{"class":78}," socat\n",[13,87,88],{},"Fedora：",[20,90,92],{"className":62,"code":91,"language":64,"meta":26,"style":26},"sudo dnf install socat\n",[28,93,94],{"__ignoreMap":26},[68,95,96,98,101,103],{"class":70,"line":71},[68,97,75],{"class":74},[68,99,100],{"class":78}," dnf",[68,102,82],{"class":78},[68,104,85],{"class":78},[53,106,107],{"id":107},"创建一对虚拟串口",[13,109,110],{},"新开一个终端，运行：",[20,112,114],{"className":62,"code":113,"language":64,"meta":26,"style":26},"socat -d -d pty,raw,echo=0 pty,raw,echo=0\n",[28,115,116],{"__ignoreMap":26},[68,117,118,120,124,126,129,132,134],{"class":70,"line":71},[68,119,50],{"class":74},[68,121,123],{"class":122},"sj4cs"," -d",[68,125,123],{"class":122},[68,127,128],{"class":78}," pty,raw,echo=",[68,130,131],{"class":122},"0",[68,133,128],{"class":78},[68,135,136],{"class":122},"0\n",[13,138,139],{},"你会看到类似输出：",[20,141,144],{"className":142,"code":143,"language":25,"meta":26},[23],"2026/05/24 12:00:00 socat[12345] N PTY is /dev/pts/3\n2026/05/24 12:00:00 socat[12345] N PTY is /dev/pts/4\n2026/05/24 12:00:00 socat[12345] N starting data transfer loop with FDs [5,5] and [7,7]\n",[28,145,143],{"__ignoreMap":26},[13,147,148],{},"这表示：",[20,150,153],{"className":151,"code":152,"language":25,"meta":26},[23],"/dev/pts/3 和 /dev/pts/4 是一对互通的虚拟串口\n程序写 /dev/pts/3，另一个终端读 /dev/pts/4 就能看到\n程序读 /dev/pts/3，另一个终端写 /dev/pts/4 就能发给程序\n",[28,154,152],{"__ignoreMap":26},[13,156,157,158,161,162,165],{},"下面示例都假设程序使用 ",[28,159,160],{},"/dev/pts/3","，另一个终端使用 ",[28,163,164],{},"/dev/pts/4","。你要按自己终端实际输出修改。",[38,167],{},[41,169,171,172,175],{"id":170},"示例-1普通-main-里同步打开串口并发送一行","示例 1：普通 ",[28,173,174],{},"main()"," 里同步打开串口并发送一行",[53,177,178],{"id":178},"程序目标",[13,180,181,182,184],{},"程序打开串口 ",[28,183,160],{},"，设置波特率 115200，然后发送：",[20,186,189],{"className":187,"code":188,"language":25,"meta":26},[23],"hello serial\n",[28,190,188],{"__ignoreMap":26},[13,192,193,194,196],{},"另一个终端从 ",[28,195,164],{}," 读到这行数据。",[53,198,199],{"id":199},"完整代码",[20,201,205],{"className":202,"code":203,"language":204,"meta":26,"style":26},"language-cpp shiki shiki-themes github-light github-dark","#include \u003Cboost/asio.hpp>\n#include \u003Cboost/system/error_code.hpp>\n#include \u003Ciostream>\n#include \u003Cstring>\n\nint main(int argc, char* argv[])\n{\n    // 程序从 main 函数开始执行，argc/argv 用来接收命令行参数。\n    std::string port_name = \"/dev/pts/3\";\n\n    if (argc >= 2)\n    {\n        port_name = argv[1];\n    }\n\n    // io_context 是 Asio 的事件循环对象，异步任务需要靠它调度。\n    boost::asio::io_context io;\n    // serial_port 表示串口设备，后续读写都通过它完成。\n    boost::asio::serial_port serial(io);\n    boost::system::error_code ec;\n\n    std::cout \u003C\u003C \"main：准备打开串口 \" \u003C\u003C port_name \u003C\u003C std::endl;\n\n    serial.open(port_name, ec);\n    if (ec)\n    {\n        std::cout \u003C\u003C \"打开串口失败：\" \u003C\u003C ec.message() \u003C\u003C std::endl;\n        return 1;\n    }\n\n    serial.set_option(boost::asio::serial_port_base::baud_rate(115200));\n    serial.set_option(boost::asio::serial_port_base::character_size(8));\n    serial.set_option(boost::asio::serial_port_base::parity(\n        boost::asio::serial_port_base::parity::none));\n    serial.set_option(boost::asio::serial_port_base::stop_bits(\n        boost::asio::serial_port_base::stop_bits::one));\n    serial.set_option(boost::asio::serial_port_base::flow_control(\n        boost::asio::serial_port_base::flow_control::none));\n\n    std::string msg = \"hello serial\\n\";\n\n    // 把缓冲区中的数据写入连接。\n    std::size_t n = boost::asio::write(serial, boost::asio::buffer(msg), ec);\n    if (ec)\n    {\n        std::cout \u003C\u003C \"发送失败：\" \u003C\u003C ec.message() \u003C\u003C std::endl;\n        return 1;\n    }\n\n    std::cout \u003C\u003C \"main：发送成功，字节数 = \" \u003C\u003C n \u003C\u003C std::endl;\n    std::cout \u003C\u003C \"main：程序结束\" \u003C\u003C std::endl;\n\n    return 0;\n}\n","cpp",[28,206,207,216,224,232,240,247,278,284,291,309,314,332,338,355,361,366,372,387,393,411,424,429,457,462,474,482,487,517,528,533,538,573,604,631,652,678,698,724,743,748,769,774,780,824,831,836,862,871,876,881,903,921,926,937],{"__ignoreMap":26},[68,208,209,213],{"class":70,"line":71},[68,210,212],{"class":211},"szBVR","#include",[68,214,215],{"class":78}," \u003Cboost/asio.hpp>\n",[68,217,219,221],{"class":70,"line":218},2,[68,220,212],{"class":211},[68,222,223],{"class":78}," \u003Cboost/system/error_code.hpp>\n",[68,225,227,229],{"class":70,"line":226},3,[68,228,212],{"class":211},[68,230,231],{"class":78}," \u003Ciostream>\n",[68,233,235,237],{"class":70,"line":234},4,[68,236,212],{"class":211},[68,238,239],{"class":78}," \u003Cstring>\n",[68,241,243],{"class":70,"line":242},5,[68,244,246],{"emptyLinePlaceholder":245},true,"\n",[68,248,250,253,256,260,262,266,269,272,275],{"class":70,"line":249},6,[68,251,252],{"class":211},"int",[68,254,255],{"class":74}," main",[68,257,259],{"class":258},"sVt8B","(",[68,261,252],{"class":211},[68,263,265],{"class":264},"s4XuR"," argc",[68,267,268],{"class":258},", ",[68,270,271],{"class":211},"char*",[68,273,274],{"class":264}," argv",[68,276,277],{"class":258},"[])\n",[68,279,281],{"class":70,"line":280},7,[68,282,283],{"class":258},"{\n",[68,285,287],{"class":70,"line":286},8,[68,288,290],{"class":289},"sJ8bj","    // 程序从 main 函数开始执行，argc/argv 用来接收命令行参数。\n",[68,292,294,297,300,303,306],{"class":70,"line":293},9,[68,295,296],{"class":74},"    std",[68,298,299],{"class":258},"::string port_name ",[68,301,302],{"class":211},"=",[68,304,305],{"class":78}," \"/dev/pts/3\"",[68,307,308],{"class":258},";\n",[68,310,312],{"class":70,"line":311},10,[68,313,246],{"emptyLinePlaceholder":245},[68,315,317,320,323,326,329],{"class":70,"line":316},11,[68,318,319],{"class":211},"    if",[68,321,322],{"class":258}," (argc ",[68,324,325],{"class":211},">=",[68,327,328],{"class":122}," 2",[68,330,331],{"class":258},")\n",[68,333,335],{"class":70,"line":334},12,[68,336,337],{"class":258},"    {\n",[68,339,341,344,346,349,352],{"class":70,"line":340},13,[68,342,343],{"class":258},"        port_name ",[68,345,302],{"class":211},[68,347,348],{"class":258}," argv[",[68,350,351],{"class":122},"1",[68,353,354],{"class":258},"];\n",[68,356,358],{"class":70,"line":357},14,[68,359,360],{"class":258},"    }\n",[68,362,364],{"class":70,"line":363},15,[68,365,246],{"emptyLinePlaceholder":245},[68,367,369],{"class":70,"line":368},16,[68,370,371],{"class":289},"    // io_context 是 Asio 的事件循环对象，异步任务需要靠它调度。\n",[68,373,375,378,381,384],{"class":70,"line":374},17,[68,376,377],{"class":74},"    boost",[68,379,380],{"class":258},"::",[68,382,383],{"class":74},"asio",[68,385,386],{"class":258},"::io_context io;\n",[68,388,390],{"class":70,"line":389},18,[68,391,392],{"class":289},"    // serial_port 表示串口设备，后续读写都通过它完成。\n",[68,394,396,398,400,402,405,408],{"class":70,"line":395},19,[68,397,377],{"class":74},[68,399,380],{"class":258},[68,401,383],{"class":74},[68,403,404],{"class":258},"::serial_port ",[68,406,407],{"class":74},"serial",[68,409,410],{"class":258},"(io);\n",[68,412,414,416,418,421],{"class":70,"line":413},20,[68,415,377],{"class":74},[68,417,380],{"class":258},[68,419,420],{"class":74},"system",[68,422,423],{"class":258},"::error_code ec;\n",[68,425,427],{"class":70,"line":426},21,[68,428,246],{"emptyLinePlaceholder":245},[68,430,432,434,437,440,443,446,449,451,454],{"class":70,"line":431},22,[68,433,296],{"class":74},[68,435,436],{"class":258},"::cout ",[68,438,439],{"class":211},"\u003C\u003C",[68,441,442],{"class":78}," \"main：准备打开串口 \"",[68,444,445],{"class":211}," \u003C\u003C",[68,447,448],{"class":258}," port_name ",[68,450,439],{"class":211},[68,452,453],{"class":74}," std",[68,455,456],{"class":258},"::endl;\n",[68,458,460],{"class":70,"line":459},23,[68,461,246],{"emptyLinePlaceholder":245},[68,463,465,468,471],{"class":70,"line":464},24,[68,466,467],{"class":258},"    serial.",[68,469,470],{"class":74},"open",[68,472,473],{"class":258},"(port_name, ec);\n",[68,475,477,479],{"class":70,"line":476},25,[68,478,319],{"class":211},[68,480,481],{"class":258}," (ec)\n",[68,483,485],{"class":70,"line":484},26,[68,486,337],{"class":258},[68,488,490,493,495,497,500,502,505,508,511,513,515],{"class":70,"line":489},27,[68,491,492],{"class":74},"        std",[68,494,436],{"class":258},[68,496,439],{"class":211},[68,498,499],{"class":78}," \"打开串口失败：\"",[68,501,445],{"class":211},[68,503,504],{"class":258}," ec.",[68,506,507],{"class":74},"message",[68,509,510],{"class":258},"() ",[68,512,439],{"class":211},[68,514,453],{"class":74},[68,516,456],{"class":258},[68,518,520,523,526],{"class":70,"line":519},28,[68,521,522],{"class":211},"        return",[68,524,525],{"class":122}," 1",[68,527,308],{"class":258},[68,529,531],{"class":70,"line":530},29,[68,532,360],{"class":258},[68,534,536],{"class":70,"line":535},30,[68,537,246],{"emptyLinePlaceholder":245},[68,539,541,543,546,548,551,553,555,557,560,562,565,567,570],{"class":70,"line":540},31,[68,542,467],{"class":258},[68,544,545],{"class":74},"set_option",[68,547,259],{"class":258},[68,549,550],{"class":74},"boost",[68,552,380],{"class":258},[68,554,383],{"class":74},[68,556,380],{"class":258},[68,558,559],{"class":74},"serial_port_base",[68,561,380],{"class":258},[68,563,564],{"class":74},"baud_rate",[68,566,259],{"class":258},[68,568,569],{"class":122},"115200",[68,571,572],{"class":258},"));\n",[68,574,576,578,580,582,584,586,588,590,592,594,597,599,602],{"class":70,"line":575},32,[68,577,467],{"class":258},[68,579,545],{"class":74},[68,581,259],{"class":258},[68,583,550],{"class":74},[68,585,380],{"class":258},[68,587,383],{"class":74},[68,589,380],{"class":258},[68,591,559],{"class":74},[68,593,380],{"class":258},[68,595,596],{"class":74},"character_size",[68,598,259],{"class":258},[68,600,601],{"class":122},"8",[68,603,572],{"class":258},[68,605,607,609,611,613,615,617,619,621,623,625,628],{"class":70,"line":606},33,[68,608,467],{"class":258},[68,610,545],{"class":74},[68,612,259],{"class":258},[68,614,550],{"class":74},[68,616,380],{"class":258},[68,618,383],{"class":74},[68,620,380],{"class":258},[68,622,559],{"class":74},[68,624,380],{"class":258},[68,626,627],{"class":74},"parity",[68,629,630],{"class":258},"(\n",[68,632,634,637,639,641,643,645,647,649],{"class":70,"line":633},34,[68,635,636],{"class":74},"        boost",[68,638,380],{"class":258},[68,640,383],{"class":74},[68,642,380],{"class":258},[68,644,559],{"class":74},[68,646,380],{"class":258},[68,648,627],{"class":74},[68,650,651],{"class":258},"::none));\n",[68,653,655,657,659,661,663,665,667,669,671,673,676],{"class":70,"line":654},35,[68,656,467],{"class":258},[68,658,545],{"class":74},[68,660,259],{"class":258},[68,662,550],{"class":74},[68,664,380],{"class":258},[68,666,383],{"class":74},[68,668,380],{"class":258},[68,670,559],{"class":74},[68,672,380],{"class":258},[68,674,675],{"class":74},"stop_bits",[68,677,630],{"class":258},[68,679,681,683,685,687,689,691,693,695],{"class":70,"line":680},36,[68,682,636],{"class":74},[68,684,380],{"class":258},[68,686,383],{"class":74},[68,688,380],{"class":258},[68,690,559],{"class":74},[68,692,380],{"class":258},[68,694,675],{"class":74},[68,696,697],{"class":258},"::one));\n",[68,699,701,703,705,707,709,711,713,715,717,719,722],{"class":70,"line":700},37,[68,702,467],{"class":258},[68,704,545],{"class":74},[68,706,259],{"class":258},[68,708,550],{"class":74},[68,710,380],{"class":258},[68,712,383],{"class":74},[68,714,380],{"class":258},[68,716,559],{"class":74},[68,718,380],{"class":258},[68,720,721],{"class":74},"flow_control",[68,723,630],{"class":258},[68,725,727,729,731,733,735,737,739,741],{"class":70,"line":726},38,[68,728,636],{"class":74},[68,730,380],{"class":258},[68,732,383],{"class":74},[68,734,380],{"class":258},[68,736,559],{"class":74},[68,738,380],{"class":258},[68,740,721],{"class":74},[68,742,651],{"class":258},[68,744,746],{"class":70,"line":745},39,[68,747,246],{"emptyLinePlaceholder":245},[68,749,751,753,756,758,761,764,767],{"class":70,"line":750},40,[68,752,296],{"class":74},[68,754,755],{"class":258},"::string msg ",[68,757,302],{"class":211},[68,759,760],{"class":78}," \"hello serial",[68,762,763],{"class":122},"\\n",[68,765,766],{"class":78},"\"",[68,768,308],{"class":258},[68,770,772],{"class":70,"line":771},41,[68,773,246],{"emptyLinePlaceholder":245},[68,775,777],{"class":70,"line":776},42,[68,778,779],{"class":289},"    // 把缓冲区中的数据写入连接。\n",[68,781,783,785,787,790,793,795,798,800,802,804,807,810,812,814,816,818,821],{"class":70,"line":782},43,[68,784,296],{"class":74},[68,786,380],{"class":258},[68,788,789],{"class":211},"size_t",[68,791,792],{"class":258}," n ",[68,794,302],{"class":211},[68,796,797],{"class":74}," boost",[68,799,380],{"class":258},[68,801,383],{"class":74},[68,803,380],{"class":258},[68,805,806],{"class":74},"write",[68,808,809],{"class":258},"(serial, ",[68,811,550],{"class":74},[68,813,380],{"class":258},[68,815,383],{"class":74},[68,817,380],{"class":258},[68,819,820],{"class":74},"buffer",[68,822,823],{"class":258},"(msg), ec);\n",[68,825,827,829],{"class":70,"line":826},44,[68,828,319],{"class":211},[68,830,481],{"class":258},[68,832,834],{"class":70,"line":833},45,[68,835,337],{"class":258},[68,837,839,841,843,845,848,850,852,854,856,858,860],{"class":70,"line":838},46,[68,840,492],{"class":74},[68,842,436],{"class":258},[68,844,439],{"class":211},[68,846,847],{"class":78}," \"发送失败：\"",[68,849,445],{"class":211},[68,851,504],{"class":258},[68,853,507],{"class":74},[68,855,510],{"class":258},[68,857,439],{"class":211},[68,859,453],{"class":74},[68,861,456],{"class":258},[68,863,865,867,869],{"class":70,"line":864},47,[68,866,522],{"class":211},[68,868,525],{"class":122},[68,870,308],{"class":258},[68,872,874],{"class":70,"line":873},48,[68,875,360],{"class":258},[68,877,879],{"class":70,"line":878},49,[68,880,246],{"emptyLinePlaceholder":245},[68,882,884,886,888,890,893,895,897,899,901],{"class":70,"line":883},50,[68,885,296],{"class":74},[68,887,436],{"class":258},[68,889,439],{"class":211},[68,891,892],{"class":78}," \"main：发送成功，字节数 = \"",[68,894,445],{"class":211},[68,896,792],{"class":258},[68,898,439],{"class":211},[68,900,453],{"class":74},[68,902,456],{"class":258},[68,904,906,908,910,912,915,917,919],{"class":70,"line":905},51,[68,907,296],{"class":74},[68,909,436],{"class":258},[68,911,439],{"class":211},[68,913,914],{"class":78}," \"main：程序结束\"",[68,916,445],{"class":211},[68,918,453],{"class":74},[68,920,456],{"class":258},[68,922,924],{"class":70,"line":923},52,[68,925,246],{"emptyLinePlaceholder":245},[68,927,929,932,935],{"class":70,"line":928},53,[68,930,931],{"class":211},"    return",[68,933,934],{"class":122}," 0",[68,936,308],{"class":258},[68,938,940],{"class":70,"line":939},54,[68,941,942],{"class":258},"}\n",[13,944,945,949],{},[946,947,948],"strong",{},"运行结果","：见下方“运行输出与时间顺序”；如果示例涉及定时器、线程、网络或外部设备，具体时间和顺序可能会随环境略有变化。",[53,951,952],{"id":952},"编译运行",[13,954,955],{},"终端 1：创建虚拟串口。",[20,957,958],{"className":62,"code":113,"language":64,"meta":26,"style":26},[28,959,960],{"__ignoreMap":26},[68,961,962,964,966,968,970,972,974],{"class":70,"line":71},[68,963,50],{"class":74},[68,965,123],{"class":122},[68,967,123],{"class":122},[68,969,128],{"class":78},[68,971,131],{"class":122},[68,973,128],{"class":78},[68,975,136],{"class":122},[13,977,978],{},"终端 2：监听另一端。",[20,980,982],{"className":62,"code":981,"language":64,"meta":26,"style":26},"cat /dev/pts/4\n",[28,983,984],{"__ignoreMap":26},[68,985,986,989],{"class":70,"line":71},[68,987,988],{"class":74},"cat",[68,990,991],{"class":78}," /dev/pts/4\n",[13,993,994],{},"终端 3：编译运行程序。",[20,996,998],{"className":62,"code":997,"language":64,"meta":26,"style":26},"g++ demo1_serial_write.cpp -o demo1_serial_write -std=c++17 -lboost_system -pthread\n./demo1_serial_write /dev/pts/3\n",[28,999,1000,1023],{"__ignoreMap":26},[68,1001,1002,1005,1008,1011,1014,1017,1020],{"class":70,"line":71},[68,1003,1004],{"class":74},"g++",[68,1006,1007],{"class":78}," demo1_serial_write.cpp",[68,1009,1010],{"class":122}," -o",[68,1012,1013],{"class":78}," demo1_serial_write",[68,1015,1016],{"class":122}," -std=c++17",[68,1018,1019],{"class":122}," -lboost_system",[68,1021,1022],{"class":122}," -pthread\n",[68,1024,1025,1028],{"class":70,"line":218},[68,1026,1027],{"class":74},"./demo1_serial_write",[68,1029,1030],{"class":78}," /dev/pts/3\n",[53,1032,1033],{"id":1033},"运行输出与时间顺序",[13,1035,1036],{},"程序终端输出：",[20,1038,1041],{"className":1039,"code":1040,"language":25,"meta":26},[23],"main：准备打开串口 /dev/pts/3\nmain：发送成功，字节数 = 13\nmain：程序结束\n",[28,1042,1040],{"__ignoreMap":26},[13,1044,1045],{},"监听终端输出：",[20,1047,1049],{"className":1048,"code":188,"language":25,"meta":26},[23],[28,1050,188],{"__ignoreMap":26},[13,1052,1053],{},"这个示例基本没有明显延迟，发送完成后程序立刻结束。",[53,1055,1056],{"id":1056},"本示例需要注意的点",[13,1058,1059,1060,1063],{},"这是同步写串口。",[28,1061,1062],{},"boost::asio::write()"," 会阻塞，直到数据写完或发生错误。",[53,1065,1066],{"id":1066},"关键函数说明",[1068,1069,1071],"h4",{"id":1070},"serialopenport_name-ec",[28,1072,1073],{},"serial.open(port_name, ec)",[13,1075,1076],{},"作用：打开串口设备。",[13,1078,1079],{},"参数：",[20,1081,1083],{"className":202,"code":1082,"language":204,"meta":26,"style":26},"port_name\n",[28,1084,1085],{"__ignoreMap":26},[68,1086,1087],{"class":70,"line":71},[68,1088,1082],{"class":258},[13,1090,1091,1092,1095,1096,1095,1099,36],{},"例如 ",[28,1093,1094],{},"/dev/ttyUSB0","、",[28,1097,1098],{},"/dev/ttyACM0",[28,1100,160],{},[20,1102,1104],{"className":202,"code":1103,"language":204,"meta":26,"style":26},"ec\n",[28,1105,1106],{"__ignoreMap":26},[68,1107,1108],{"class":70,"line":71},[68,1109,1103],{"class":258},[13,1111,1112],{},"用于接收错误信息。这样写不会抛异常，更适合教程和机器人工程。",[1068,1114,1116],{"id":1115},"serialset_option",[28,1117,1118],{},"serial.set_option(...)",[13,1120,1121],{},"作用：设置串口参数，例如波特率、数据位、校验位、停止位、流控。",[1068,1123,1125],{"id":1124},"boostasiowriteserial-boostasiobuffermsg-ec",[28,1126,1127],{},"boost::asio::write(serial, boost::asio::buffer(msg), ec)",[13,1129,1130],{},"作用：同步写数据。",[13,1132,1133],{},"返回值：实际写入的字节数。",[38,1135],{},[41,1137,1139,1140,1142],{"id":1138},"示例-2普通-main-里同步读取一行串口数据","示例 2：普通 ",[28,1141,174],{}," 里同步读取一行串口数据",[53,1144,178],{"id":1145},"程序目标-1",[13,1147,1148,1149,1151],{},"程序打开串口并阻塞等待，直到收到 ",[28,1150,763],{}," 为止。",[53,1153,199],{"id":1154},"完整代码-1",[20,1156,1158],{"className":202,"code":1157,"language":204,"meta":26,"style":26},"#include \u003Cboost/asio.hpp>\n#include \u003Cboost/system/error_code.hpp>\n#include \u003Ciostream>\n#include \u003Cistream>\n#include \u003Cstring>\n\nint main(int argc, char* argv[])\n{\n    // 程序从 main 函数开始执行，argc/argv 用来接收命令行参数。\n    std::string port_name = \"/dev/pts/3\";\n\n    if (argc >= 2)\n    {\n        port_name = argv[1];\n    }\n\n    // io_context 是 Asio 的事件循环对象，异步任务需要靠它调度。\n    boost::asio::io_context io;\n    // serial_port 表示串口设备，后续读写都通过它完成。\n    boost::asio::serial_port serial(io);\n    boost::system::error_code ec;\n\n    serial.open(port_name, ec);\n    if (ec)\n    {\n        std::cout \u003C\u003C \"打开串口失败：\" \u003C\u003C ec.message() \u003C\u003C std::endl;\n        return 1;\n    }\n\n    // 设置串口或 socket 参数，例如波特率、数据位或超时相关配置。\n    serial.set_option(boost::asio::serial_port_base::baud_rate(115200));\n\n    boost::asio::streambuf buffer;\n\n    std::cout \u003C\u003C \"main：等待串口收到一行数据，以换行符结束\" \u003C\u003C std::endl;\n\n    std::size_t n = boost::asio::read_until(serial, buffer, '\\n', ec);\n    if (ec)\n    {\n        std::cout \u003C\u003C \"读取失败：\" \u003C\u003C ec.message() \u003C\u003C std::endl;\n        return 1;\n    }\n\n    std::istream is(&buffer);\n    std::string line;\n    std::getline(is, line);\n\n    std::cout \u003C\u003C \"main：读取到字节数 = \" \u003C\u003C n \u003C\u003C std::endl;\n    std::cout \u003C\u003C \"main：读取到一行 = \" \u003C\u003C line \u003C\u003C std::endl;\n\n    return 0;\n}\n",[28,1159,1160,1166,1172,1178,1185,1191,1195,1215,1219,1223,1235,1239,1251,1255,1267,1271,1275,1279,1289,1293,1307,1317,1321,1329,1335,1339,1363,1371,1375,1379,1384,1412,1416,1427,1431,1448,1452,1488,1494,1498,1523,1531,1535,1539,1557,1564,1576,1580,1601,1623,1627,1635],{"__ignoreMap":26},[68,1161,1162,1164],{"class":70,"line":71},[68,1163,212],{"class":211},[68,1165,215],{"class":78},[68,1167,1168,1170],{"class":70,"line":218},[68,1169,212],{"class":211},[68,1171,223],{"class":78},[68,1173,1174,1176],{"class":70,"line":226},[68,1175,212],{"class":211},[68,1177,231],{"class":78},[68,1179,1180,1182],{"class":70,"line":234},[68,1181,212],{"class":211},[68,1183,1184],{"class":78}," \u003Cistream>\n",[68,1186,1187,1189],{"class":70,"line":242},[68,1188,212],{"class":211},[68,1190,239],{"class":78},[68,1192,1193],{"class":70,"line":249},[68,1194,246],{"emptyLinePlaceholder":245},[68,1196,1197,1199,1201,1203,1205,1207,1209,1211,1213],{"class":70,"line":280},[68,1198,252],{"class":211},[68,1200,255],{"class":74},[68,1202,259],{"class":258},[68,1204,252],{"class":211},[68,1206,265],{"class":264},[68,1208,268],{"class":258},[68,1210,271],{"class":211},[68,1212,274],{"class":264},[68,1214,277],{"class":258},[68,1216,1217],{"class":70,"line":286},[68,1218,283],{"class":258},[68,1220,1221],{"class":70,"line":293},[68,1222,290],{"class":289},[68,1224,1225,1227,1229,1231,1233],{"class":70,"line":311},[68,1226,296],{"class":74},[68,1228,299],{"class":258},[68,1230,302],{"class":211},[68,1232,305],{"class":78},[68,1234,308],{"class":258},[68,1236,1237],{"class":70,"line":316},[68,1238,246],{"emptyLinePlaceholder":245},[68,1240,1241,1243,1245,1247,1249],{"class":70,"line":334},[68,1242,319],{"class":211},[68,1244,322],{"class":258},[68,1246,325],{"class":211},[68,1248,328],{"class":122},[68,1250,331],{"class":258},[68,1252,1253],{"class":70,"line":340},[68,1254,337],{"class":258},[68,1256,1257,1259,1261,1263,1265],{"class":70,"line":357},[68,1258,343],{"class":258},[68,1260,302],{"class":211},[68,1262,348],{"class":258},[68,1264,351],{"class":122},[68,1266,354],{"class":258},[68,1268,1269],{"class":70,"line":363},[68,1270,360],{"class":258},[68,1272,1273],{"class":70,"line":368},[68,1274,246],{"emptyLinePlaceholder":245},[68,1276,1277],{"class":70,"line":374},[68,1278,371],{"class":289},[68,1280,1281,1283,1285,1287],{"class":70,"line":389},[68,1282,377],{"class":74},[68,1284,380],{"class":258},[68,1286,383],{"class":74},[68,1288,386],{"class":258},[68,1290,1291],{"class":70,"line":395},[68,1292,392],{"class":289},[68,1294,1295,1297,1299,1301,1303,1305],{"class":70,"line":413},[68,1296,377],{"class":74},[68,1298,380],{"class":258},[68,1300,383],{"class":74},[68,1302,404],{"class":258},[68,1304,407],{"class":74},[68,1306,410],{"class":258},[68,1308,1309,1311,1313,1315],{"class":70,"line":426},[68,1310,377],{"class":74},[68,1312,380],{"class":258},[68,1314,420],{"class":74},[68,1316,423],{"class":258},[68,1318,1319],{"class":70,"line":431},[68,1320,246],{"emptyLinePlaceholder":245},[68,1322,1323,1325,1327],{"class":70,"line":459},[68,1324,467],{"class":258},[68,1326,470],{"class":74},[68,1328,473],{"class":258},[68,1330,1331,1333],{"class":70,"line":464},[68,1332,319],{"class":211},[68,1334,481],{"class":258},[68,1336,1337],{"class":70,"line":476},[68,1338,337],{"class":258},[68,1340,1341,1343,1345,1347,1349,1351,1353,1355,1357,1359,1361],{"class":70,"line":484},[68,1342,492],{"class":74},[68,1344,436],{"class":258},[68,1346,439],{"class":211},[68,1348,499],{"class":78},[68,1350,445],{"class":211},[68,1352,504],{"class":258},[68,1354,507],{"class":74},[68,1356,510],{"class":258},[68,1358,439],{"class":211},[68,1360,453],{"class":74},[68,1362,456],{"class":258},[68,1364,1365,1367,1369],{"class":70,"line":489},[68,1366,522],{"class":211},[68,1368,525],{"class":122},[68,1370,308],{"class":258},[68,1372,1373],{"class":70,"line":519},[68,1374,360],{"class":258},[68,1376,1377],{"class":70,"line":530},[68,1378,246],{"emptyLinePlaceholder":245},[68,1380,1381],{"class":70,"line":535},[68,1382,1383],{"class":289},"    // 设置串口或 socket 参数，例如波特率、数据位或超时相关配置。\n",[68,1385,1386,1388,1390,1392,1394,1396,1398,1400,1402,1404,1406,1408,1410],{"class":70,"line":540},[68,1387,467],{"class":258},[68,1389,545],{"class":74},[68,1391,259],{"class":258},[68,1393,550],{"class":74},[68,1395,380],{"class":258},[68,1397,383],{"class":74},[68,1399,380],{"class":258},[68,1401,559],{"class":74},[68,1403,380],{"class":258},[68,1405,564],{"class":74},[68,1407,259],{"class":258},[68,1409,569],{"class":122},[68,1411,572],{"class":258},[68,1413,1414],{"class":70,"line":575},[68,1415,246],{"emptyLinePlaceholder":245},[68,1417,1418,1420,1422,1424],{"class":70,"line":606},[68,1419,377],{"class":74},[68,1421,380],{"class":258},[68,1423,383],{"class":74},[68,1425,1426],{"class":258},"::streambuf buffer;\n",[68,1428,1429],{"class":70,"line":633},[68,1430,246],{"emptyLinePlaceholder":245},[68,1432,1433,1435,1437,1439,1442,1444,1446],{"class":70,"line":654},[68,1434,296],{"class":74},[68,1436,436],{"class":258},[68,1438,439],{"class":211},[68,1440,1441],{"class":78}," \"main：等待串口收到一行数据，以换行符结束\"",[68,1443,445],{"class":211},[68,1445,453],{"class":74},[68,1447,456],{"class":258},[68,1449,1450],{"class":70,"line":680},[68,1451,246],{"emptyLinePlaceholder":245},[68,1453,1454,1456,1458,1460,1462,1464,1466,1468,1470,1472,1475,1478,1481,1483,1485],{"class":70,"line":700},[68,1455,296],{"class":74},[68,1457,380],{"class":258},[68,1459,789],{"class":211},[68,1461,792],{"class":258},[68,1463,302],{"class":211},[68,1465,797],{"class":74},[68,1467,380],{"class":258},[68,1469,383],{"class":74},[68,1471,380],{"class":258},[68,1473,1474],{"class":74},"read_until",[68,1476,1477],{"class":258},"(serial, buffer, ",[68,1479,1480],{"class":78},"'",[68,1482,763],{"class":122},[68,1484,1480],{"class":78},[68,1486,1487],{"class":258},", ec);\n",[68,1489,1490,1492],{"class":70,"line":726},[68,1491,319],{"class":211},[68,1493,481],{"class":258},[68,1495,1496],{"class":70,"line":745},[68,1497,337],{"class":258},[68,1499,1500,1502,1504,1506,1509,1511,1513,1515,1517,1519,1521],{"class":70,"line":750},[68,1501,492],{"class":74},[68,1503,436],{"class":258},[68,1505,439],{"class":211},[68,1507,1508],{"class":78}," \"读取失败：\"",[68,1510,445],{"class":211},[68,1512,504],{"class":258},[68,1514,507],{"class":74},[68,1516,510],{"class":258},[68,1518,439],{"class":211},[68,1520,453],{"class":74},[68,1522,456],{"class":258},[68,1524,1525,1527,1529],{"class":70,"line":771},[68,1526,522],{"class":211},[68,1528,525],{"class":122},[68,1530,308],{"class":258},[68,1532,1533],{"class":70,"line":776},[68,1534,360],{"class":258},[68,1536,1537],{"class":70,"line":782},[68,1538,246],{"emptyLinePlaceholder":245},[68,1540,1541,1543,1546,1549,1551,1554],{"class":70,"line":826},[68,1542,296],{"class":74},[68,1544,1545],{"class":258},"::istream ",[68,1547,1548],{"class":74},"is",[68,1550,259],{"class":258},[68,1552,1553],{"class":211},"&",[68,1555,1556],{"class":258},"buffer);\n",[68,1558,1559,1561],{"class":70,"line":833},[68,1560,296],{"class":74},[68,1562,1563],{"class":258},"::string line;\n",[68,1565,1566,1568,1570,1573],{"class":70,"line":838},[68,1567,296],{"class":74},[68,1569,380],{"class":258},[68,1571,1572],{"class":74},"getline",[68,1574,1575],{"class":258},"(is, line);\n",[68,1577,1578],{"class":70,"line":864},[68,1579,246],{"emptyLinePlaceholder":245},[68,1581,1582,1584,1586,1588,1591,1593,1595,1597,1599],{"class":70,"line":873},[68,1583,296],{"class":74},[68,1585,436],{"class":258},[68,1587,439],{"class":211},[68,1589,1590],{"class":78}," \"main：读取到字节数 = \"",[68,1592,445],{"class":211},[68,1594,792],{"class":258},[68,1596,439],{"class":211},[68,1598,453],{"class":74},[68,1600,456],{"class":258},[68,1602,1603,1605,1607,1609,1612,1614,1617,1619,1621],{"class":70,"line":878},[68,1604,296],{"class":74},[68,1606,436],{"class":258},[68,1608,439],{"class":211},[68,1610,1611],{"class":78}," \"main：读取到一行 = \"",[68,1613,445],{"class":211},[68,1615,1616],{"class":258}," line ",[68,1618,439],{"class":211},[68,1620,453],{"class":74},[68,1622,456],{"class":258},[68,1624,1625],{"class":70,"line":883},[68,1626,246],{"emptyLinePlaceholder":245},[68,1628,1629,1631,1633],{"class":70,"line":905},[68,1630,931],{"class":211},[68,1632,934],{"class":122},[68,1634,308],{"class":258},[68,1636,1637],{"class":70,"line":923},[68,1638,942],{"class":258},[13,1640,1641,949],{},[946,1642,948],{},[53,1644,952],{"id":1645},"编译运行-1",[13,1647,955],{},[20,1649,1650],{"className":62,"code":113,"language":64,"meta":26,"style":26},[28,1651,1652],{"__ignoreMap":26},[68,1653,1654,1656,1658,1660,1662,1664,1666],{"class":70,"line":71},[68,1655,50],{"class":74},[68,1657,123],{"class":122},[68,1659,123],{"class":122},[68,1661,128],{"class":78},[68,1663,131],{"class":122},[68,1665,128],{"class":78},[68,1667,136],{"class":122},[13,1669,1670],{},"终端 2：运行程序。",[20,1672,1674],{"className":62,"code":1673,"language":64,"meta":26,"style":26},"g++ demo2_serial_read_line.cpp -o demo2_serial_read_line -std=c++17 -lboost_system -pthread\n./demo2_serial_read_line /dev/pts/3\n",[28,1675,1676,1694],{"__ignoreMap":26},[68,1677,1678,1680,1683,1685,1688,1690,1692],{"class":70,"line":71},[68,1679,1004],{"class":74},[68,1681,1682],{"class":78}," demo2_serial_read_line.cpp",[68,1684,1010],{"class":122},[68,1686,1687],{"class":78}," demo2_serial_read_line",[68,1689,1016],{"class":122},[68,1691,1019],{"class":122},[68,1693,1022],{"class":122},[68,1695,1696,1699],{"class":70,"line":218},[68,1697,1698],{"class":74},"./demo2_serial_read_line",[68,1700,1030],{"class":78},[13,1702,1703],{},"终端 3：向另一端写数据。",[20,1705,1707],{"className":62,"code":1706,"language":64,"meta":26,"style":26},"echo \"stm32 ok\" > /dev/pts/4\n",[28,1708,1709],{"__ignoreMap":26},[68,1710,1711,1714,1717,1720],{"class":70,"line":71},[68,1712,1713],{"class":122},"echo",[68,1715,1716],{"class":78}," \"stm32 ok\"",[68,1718,1719],{"class":211}," >",[68,1721,991],{"class":78},[53,1723,1033],{"id":1724},"运行输出与时间顺序-1",[13,1726,1727],{},"程序启动后立刻输出：",[20,1729,1732],{"className":1730,"code":1731,"language":25,"meta":26},[23],"main：等待串口收到一行数据，以换行符结束\n",[28,1733,1731],{"__ignoreMap":26},[13,1735,1736],{},"然后程序阻塞。你在另一个终端执行：",[20,1738,1739],{"className":62,"code":1706,"language":64,"meta":26,"style":26},[28,1740,1741],{"__ignoreMap":26},[68,1742,1743,1745,1747,1749],{"class":70,"line":71},[68,1744,1713],{"class":122},[68,1746,1716],{"class":78},[68,1748,1719],{"class":211},[68,1750,991],{"class":78},[13,1752,1753],{},"程序继续输出：",[20,1755,1758],{"className":1756,"code":1757,"language":25,"meta":26},[23],"main：读取到字节数 = 9\nmain：读取到一行 = stm32 ok\n",[28,1759,1757],{"__ignoreMap":26},[13,1761,1762],{},"这里的等待时间取决于你什么时候发送数据。",[53,1764,1056],{"id":1765},"本示例需要注意的点-1",[13,1767,1768,1771],{},[28,1769,1770],{},"read_until()"," 是同步阻塞函数。没有收到换行符之前，它会一直卡住。",[13,1773,1774],{},"如果你在 ROS2 回调里直接这样读串口，可能导致整个节点响应变慢。",[53,1776,1066],{"id":1777},"关键函数说明-1",[1068,1779,1781],{"id":1780},"boostasioread_untilserial-buffer-n-ec",[28,1782,1783],{},"boost::asio::read_until(serial, buffer, '\\n', ec)",[13,1785,1786,1787,36],{},"作用：从串口读取数据，直到遇到换行符 ",[28,1788,763],{},[13,1790,1791],{},"返回值：至少读取到分隔符为止的字节数。",[13,1793,1794,1795,1798],{},"注意：",[28,1796,1797],{},"streambuf"," 里可能还留有额外数据，后续读取时要注意处理。",[38,1800],{},[41,1802,1804,1805,1807],{"id":1803},"示例-3普通-main-里异步读取一行串口数据","示例 3：普通 ",[28,1806,174],{}," 里异步读取一行串口数据",[53,1809,178],{"id":1810},"程序目标-2",[13,1812,1813],{},"把示例 2 改成异步版本：",[1815,1816,1817,1824,1830,1833,1836],"ol",{},[1818,1819,1820,1823],"li",{},[28,1821,1822],{},"async_read_until()"," 注册读取任务；",[1818,1825,1826,1829],{},[28,1827,1828],{},"io.run()"," 开始等待；",[1818,1831,1832],{},"另一端发送一行数据；",[1818,1834,1835],{},"回调函数执行；",[1818,1837,1838,1840],{},[28,1839,1828],{}," 返回。",[53,1842,199],{"id":1843},"完整代码-2",[20,1845,1847],{"className":202,"code":1846,"language":204,"meta":26,"style":26},"#include \u003Cboost/asio.hpp>\n#include \u003Cboost/system/error_code.hpp>\n#include \u003Cfunctional>\n#include \u003Ciostream>\n#include \u003Cistream>\n#include \u003Cstring>\n\nvoid on_read_line(const boost::system::error_code& ec,\n                  std::size_t bytes_transferred,\n                  boost::asio::streambuf* buffer)\n{\n    if (ec)\n    {\n        std::cout \u003C\u003C \"on_read_line：读取失败：\" \u003C\u003C ec.message() \u003C\u003C std::endl;\n        return;\n    }\n\n    std::istream is(buffer);\n    std::string line;\n    std::getline(is, line);\n\n    std::cout \u003C\u003C \"on_read_line：bytes_transferred = \" \u003C\u003C bytes_transferred \u003C\u003C std::endl;\n    std::cout \u003C\u003C \"on_read_line：收到一行 = \" \u003C\u003C line \u003C\u003C std::endl;\n}\n\nint main(int argc, char* argv[])\n{\n    // 程序从 main 函数开始执行，argc/argv 用来接收命令行参数。\n    std::string port_name = \"/dev/pts/3\";\n\n    if (argc >= 2)\n    {\n        port_name = argv[1];\n    }\n\n    // io_context 是 Asio 的事件循环对象，异步任务需要靠它调度。\n    boost::asio::io_context io;\n    // serial_port 表示串口设备，后续读写都通过它完成。\n    boost::asio::serial_port serial(io);\n    boost::system::error_code ec;\n\n    serial.open(port_name, ec);\n    if (ec)\n    {\n        std::cout \u003C\u003C \"打开串口失败：\" \u003C\u003C ec.message() \u003C\u003C std::endl;\n        return 1;\n    }\n\n    serial.set_option(boost::asio::serial_port_base::baud_rate(115200));\n\n    boost::asio::streambuf buffer;\n\n    std::cout \u003C\u003C \"main：注册 async_read_until\" \u003C\u003C std::endl;\n\n    boost::asio::async_read_until(serial,\n                                  buffer,\n                                  '\\n',\n                                  std::bind(on_read_line,\n                                            std::placeholders::_1,\n                                            std::placeholders::_2,\n                                            &buffer));\n\n    std::cout \u003C\u003C \"main：async_read_until 已返回，准备 io.run()\" \u003C\u003C std::endl;\n\n    // 启动事件循环，前面注册的异步任务会在这里被调度执行。\n    io.run();\n\n    std::cout \u003C\u003C \"main：io.run() 返回\" \u003C\u003C std::endl;\n\n    return 0;\n}\n",[28,1848,1849,1855,1861,1868,1874,1880,1886,1890,1922,1936,1957,1961,1967,1971,1996,2002,2006,2010,2021,2027,2037,2041,2063,2084,2088,2092,2112,2116,2120,2132,2136,2148,2152,2164,2168,2172,2176,2186,2190,2204,2214,2218,2226,2232,2236,2260,2268,2272,2276,2304,2308,2318,2322,2339,2343,2360,2366,2378,2392,2406,2418,2427,2432,2450,2455,2461,2473,2478,2496,2501,2510],{"__ignoreMap":26},[68,1850,1851,1853],{"class":70,"line":71},[68,1852,212],{"class":211},[68,1854,215],{"class":78},[68,1856,1857,1859],{"class":70,"line":218},[68,1858,212],{"class":211},[68,1860,223],{"class":78},[68,1862,1863,1865],{"class":70,"line":226},[68,1864,212],{"class":211},[68,1866,1867],{"class":78}," \u003Cfunctional>\n",[68,1869,1870,1872],{"class":70,"line":234},[68,1871,212],{"class":211},[68,1873,231],{"class":78},[68,1875,1876,1878],{"class":70,"line":242},[68,1877,212],{"class":211},[68,1879,1184],{"class":78},[68,1881,1882,1884],{"class":70,"line":249},[68,1883,212],{"class":211},[68,1885,239],{"class":78},[68,1887,1888],{"class":70,"line":280},[68,1889,246],{"emptyLinePlaceholder":245},[68,1891,1892,1895,1898,1900,1903,1905,1907,1909,1911,1914,1916,1919],{"class":70,"line":286},[68,1893,1894],{"class":211},"void",[68,1896,1897],{"class":74}," on_read_line",[68,1899,259],{"class":258},[68,1901,1902],{"class":211},"const",[68,1904,797],{"class":74},[68,1906,380],{"class":258},[68,1908,420],{"class":74},[68,1910,380],{"class":258},[68,1912,1913],{"class":74},"error_code",[68,1915,1553],{"class":211},[68,1917,1918],{"class":264}," ec",[68,1920,1921],{"class":258},",\n",[68,1923,1924,1927,1929,1931,1934],{"class":70,"line":293},[68,1925,1926],{"class":74},"                  std",[68,1928,380],{"class":258},[68,1930,789],{"class":211},[68,1932,1933],{"class":264}," bytes_transferred",[68,1935,1921],{"class":258},[68,1937,1938,1941,1943,1945,1947,1949,1952,1955],{"class":70,"line":311},[68,1939,1940],{"class":74},"                  boost",[68,1942,380],{"class":258},[68,1944,383],{"class":74},[68,1946,380],{"class":258},[68,1948,1797],{"class":74},[68,1950,1951],{"class":211},"*",[68,1953,1954],{"class":264}," buffer",[68,1956,331],{"class":258},[68,1958,1959],{"class":70,"line":316},[68,1960,283],{"class":258},[68,1962,1963,1965],{"class":70,"line":334},[68,1964,319],{"class":211},[68,1966,481],{"class":258},[68,1968,1969],{"class":70,"line":340},[68,1970,337],{"class":258},[68,1972,1973,1975,1977,1979,1982,1984,1986,1988,1990,1992,1994],{"class":70,"line":357},[68,1974,492],{"class":74},[68,1976,436],{"class":258},[68,1978,439],{"class":211},[68,1980,1981],{"class":78}," \"on_read_line：读取失败：\"",[68,1983,445],{"class":211},[68,1985,504],{"class":258},[68,1987,507],{"class":74},[68,1989,510],{"class":258},[68,1991,439],{"class":211},[68,1993,453],{"class":74},[68,1995,456],{"class":258},[68,1997,1998,2000],{"class":70,"line":363},[68,1999,522],{"class":211},[68,2001,308],{"class":258},[68,2003,2004],{"class":70,"line":368},[68,2005,360],{"class":258},[68,2007,2008],{"class":70,"line":374},[68,2009,246],{"emptyLinePlaceholder":245},[68,2011,2012,2014,2016,2018],{"class":70,"line":389},[68,2013,296],{"class":74},[68,2015,1545],{"class":258},[68,2017,1548],{"class":74},[68,2019,2020],{"class":258},"(buffer);\n",[68,2022,2023,2025],{"class":70,"line":395},[68,2024,296],{"class":74},[68,2026,1563],{"class":258},[68,2028,2029,2031,2033,2035],{"class":70,"line":413},[68,2030,296],{"class":74},[68,2032,380],{"class":258},[68,2034,1572],{"class":74},[68,2036,1575],{"class":258},[68,2038,2039],{"class":70,"line":426},[68,2040,246],{"emptyLinePlaceholder":245},[68,2042,2043,2045,2047,2049,2052,2054,2057,2059,2061],{"class":70,"line":431},[68,2044,296],{"class":74},[68,2046,436],{"class":258},[68,2048,439],{"class":211},[68,2050,2051],{"class":78}," \"on_read_line：bytes_transferred = \"",[68,2053,445],{"class":211},[68,2055,2056],{"class":258}," bytes_transferred ",[68,2058,439],{"class":211},[68,2060,453],{"class":74},[68,2062,456],{"class":258},[68,2064,2065,2067,2069,2071,2074,2076,2078,2080,2082],{"class":70,"line":459},[68,2066,296],{"class":74},[68,2068,436],{"class":258},[68,2070,439],{"class":211},[68,2072,2073],{"class":78}," \"on_read_line：收到一行 = \"",[68,2075,445],{"class":211},[68,2077,1616],{"class":258},[68,2079,439],{"class":211},[68,2081,453],{"class":74},[68,2083,456],{"class":258},[68,2085,2086],{"class":70,"line":464},[68,2087,942],{"class":258},[68,2089,2090],{"class":70,"line":476},[68,2091,246],{"emptyLinePlaceholder":245},[68,2093,2094,2096,2098,2100,2102,2104,2106,2108,2110],{"class":70,"line":484},[68,2095,252],{"class":211},[68,2097,255],{"class":74},[68,2099,259],{"class":258},[68,2101,252],{"class":211},[68,2103,265],{"class":264},[68,2105,268],{"class":258},[68,2107,271],{"class":211},[68,2109,274],{"class":264},[68,2111,277],{"class":258},[68,2113,2114],{"class":70,"line":489},[68,2115,283],{"class":258},[68,2117,2118],{"class":70,"line":519},[68,2119,290],{"class":289},[68,2121,2122,2124,2126,2128,2130],{"class":70,"line":530},[68,2123,296],{"class":74},[68,2125,299],{"class":258},[68,2127,302],{"class":211},[68,2129,305],{"class":78},[68,2131,308],{"class":258},[68,2133,2134],{"class":70,"line":535},[68,2135,246],{"emptyLinePlaceholder":245},[68,2137,2138,2140,2142,2144,2146],{"class":70,"line":540},[68,2139,319],{"class":211},[68,2141,322],{"class":258},[68,2143,325],{"class":211},[68,2145,328],{"class":122},[68,2147,331],{"class":258},[68,2149,2150],{"class":70,"line":575},[68,2151,337],{"class":258},[68,2153,2154,2156,2158,2160,2162],{"class":70,"line":606},[68,2155,343],{"class":258},[68,2157,302],{"class":211},[68,2159,348],{"class":258},[68,2161,351],{"class":122},[68,2163,354],{"class":258},[68,2165,2166],{"class":70,"line":633},[68,2167,360],{"class":258},[68,2169,2170],{"class":70,"line":654},[68,2171,246],{"emptyLinePlaceholder":245},[68,2173,2174],{"class":70,"line":680},[68,2175,371],{"class":289},[68,2177,2178,2180,2182,2184],{"class":70,"line":700},[68,2179,377],{"class":74},[68,2181,380],{"class":258},[68,2183,383],{"class":74},[68,2185,386],{"class":258},[68,2187,2188],{"class":70,"line":726},[68,2189,392],{"class":289},[68,2191,2192,2194,2196,2198,2200,2202],{"class":70,"line":745},[68,2193,377],{"class":74},[68,2195,380],{"class":258},[68,2197,383],{"class":74},[68,2199,404],{"class":258},[68,2201,407],{"class":74},[68,2203,410],{"class":258},[68,2205,2206,2208,2210,2212],{"class":70,"line":750},[68,2207,377],{"class":74},[68,2209,380],{"class":258},[68,2211,420],{"class":74},[68,2213,423],{"class":258},[68,2215,2216],{"class":70,"line":771},[68,2217,246],{"emptyLinePlaceholder":245},[68,2219,2220,2222,2224],{"class":70,"line":776},[68,2221,467],{"class":258},[68,2223,470],{"class":74},[68,2225,473],{"class":258},[68,2227,2228,2230],{"class":70,"line":782},[68,2229,319],{"class":211},[68,2231,481],{"class":258},[68,2233,2234],{"class":70,"line":826},[68,2235,337],{"class":258},[68,2237,2238,2240,2242,2244,2246,2248,2250,2252,2254,2256,2258],{"class":70,"line":833},[68,2239,492],{"class":74},[68,2241,436],{"class":258},[68,2243,439],{"class":211},[68,2245,499],{"class":78},[68,2247,445],{"class":211},[68,2249,504],{"class":258},[68,2251,507],{"class":74},[68,2253,510],{"class":258},[68,2255,439],{"class":211},[68,2257,453],{"class":74},[68,2259,456],{"class":258},[68,2261,2262,2264,2266],{"class":70,"line":838},[68,2263,522],{"class":211},[68,2265,525],{"class":122},[68,2267,308],{"class":258},[68,2269,2270],{"class":70,"line":864},[68,2271,360],{"class":258},[68,2273,2274],{"class":70,"line":873},[68,2275,246],{"emptyLinePlaceholder":245},[68,2277,2278,2280,2282,2284,2286,2288,2290,2292,2294,2296,2298,2300,2302],{"class":70,"line":878},[68,2279,467],{"class":258},[68,2281,545],{"class":74},[68,2283,259],{"class":258},[68,2285,550],{"class":74},[68,2287,380],{"class":258},[68,2289,383],{"class":74},[68,2291,380],{"class":258},[68,2293,559],{"class":74},[68,2295,380],{"class":258},[68,2297,564],{"class":74},[68,2299,259],{"class":258},[68,2301,569],{"class":122},[68,2303,572],{"class":258},[68,2305,2306],{"class":70,"line":883},[68,2307,246],{"emptyLinePlaceholder":245},[68,2309,2310,2312,2314,2316],{"class":70,"line":905},[68,2311,377],{"class":74},[68,2313,380],{"class":258},[68,2315,383],{"class":74},[68,2317,1426],{"class":258},[68,2319,2320],{"class":70,"line":923},[68,2321,246],{"emptyLinePlaceholder":245},[68,2323,2324,2326,2328,2330,2333,2335,2337],{"class":70,"line":928},[68,2325,296],{"class":74},[68,2327,436],{"class":258},[68,2329,439],{"class":211},[68,2331,2332],{"class":78}," \"main：注册 async_read_until\"",[68,2334,445],{"class":211},[68,2336,453],{"class":74},[68,2338,456],{"class":258},[68,2340,2341],{"class":70,"line":939},[68,2342,246],{"emptyLinePlaceholder":245},[68,2344,2346,2348,2350,2352,2354,2357],{"class":70,"line":2345},55,[68,2347,377],{"class":74},[68,2349,380],{"class":258},[68,2351,383],{"class":74},[68,2353,380],{"class":258},[68,2355,2356],{"class":74},"async_read_until",[68,2358,2359],{"class":258},"(serial,\n",[68,2361,2363],{"class":70,"line":2362},56,[68,2364,2365],{"class":258},"                                  buffer,\n",[68,2367,2369,2372,2374,2376],{"class":70,"line":2368},57,[68,2370,2371],{"class":78},"                                  '",[68,2373,763],{"class":122},[68,2375,1480],{"class":78},[68,2377,1921],{"class":258},[68,2379,2381,2384,2386,2389],{"class":70,"line":2380},58,[68,2382,2383],{"class":74},"                                  std",[68,2385,380],{"class":258},[68,2387,2388],{"class":74},"bind",[68,2390,2391],{"class":258},"(on_read_line,\n",[68,2393,2395,2398,2400,2403],{"class":70,"line":2394},59,[68,2396,2397],{"class":74},"                                            std",[68,2399,380],{"class":258},[68,2401,2402],{"class":74},"placeholders",[68,2404,2405],{"class":258},"::_1,\n",[68,2407,2409,2411,2413,2415],{"class":70,"line":2408},60,[68,2410,2397],{"class":74},[68,2412,380],{"class":258},[68,2414,2402],{"class":74},[68,2416,2417],{"class":258},"::_2,\n",[68,2419,2421,2424],{"class":70,"line":2420},61,[68,2422,2423],{"class":211},"                                            &",[68,2425,2426],{"class":258},"buffer));\n",[68,2428,2430],{"class":70,"line":2429},62,[68,2431,246],{"emptyLinePlaceholder":245},[68,2433,2435,2437,2439,2441,2444,2446,2448],{"class":70,"line":2434},63,[68,2436,296],{"class":74},[68,2438,436],{"class":258},[68,2440,439],{"class":211},[68,2442,2443],{"class":78}," \"main：async_read_until 已返回，准备 io.run()\"",[68,2445,445],{"class":211},[68,2447,453],{"class":74},[68,2449,456],{"class":258},[68,2451,2453],{"class":70,"line":2452},64,[68,2454,246],{"emptyLinePlaceholder":245},[68,2456,2458],{"class":70,"line":2457},65,[68,2459,2460],{"class":289},"    // 启动事件循环，前面注册的异步任务会在这里被调度执行。\n",[68,2462,2464,2467,2470],{"class":70,"line":2463},66,[68,2465,2466],{"class":258},"    io.",[68,2468,2469],{"class":74},"run",[68,2471,2472],{"class":258},"();\n",[68,2474,2476],{"class":70,"line":2475},67,[68,2477,246],{"emptyLinePlaceholder":245},[68,2479,2481,2483,2485,2487,2490,2492,2494],{"class":70,"line":2480},68,[68,2482,296],{"class":74},[68,2484,436],{"class":258},[68,2486,439],{"class":211},[68,2488,2489],{"class":78}," \"main：io.run() 返回\"",[68,2491,445],{"class":211},[68,2493,453],{"class":74},[68,2495,456],{"class":258},[68,2497,2499],{"class":70,"line":2498},69,[68,2500,246],{"emptyLinePlaceholder":245},[68,2502,2504,2506,2508],{"class":70,"line":2503},70,[68,2505,931],{"class":211},[68,2507,934],{"class":122},[68,2509,308],{"class":258},[68,2511,2513],{"class":70,"line":2512},71,[68,2514,942],{"class":258},[13,2516,2517,949],{},[946,2518,948],{},[53,2520,952],{"id":2521},"编译运行-2",[13,2523,955],{},[20,2525,2526],{"className":62,"code":113,"language":64,"meta":26,"style":26},[28,2527,2528],{"__ignoreMap":26},[68,2529,2530,2532,2534,2536,2538,2540,2542],{"class":70,"line":71},[68,2531,50],{"class":74},[68,2533,123],{"class":122},[68,2535,123],{"class":122},[68,2537,128],{"class":78},[68,2539,131],{"class":122},[68,2541,128],{"class":78},[68,2543,136],{"class":122},[13,2545,1670],{},[20,2547,2549],{"className":62,"code":2548,"language":64,"meta":26,"style":26},"g++ demo3_async_serial_read.cpp -o demo3_async_serial_read -std=c++17 -lboost_system -pthread\n./demo3_async_serial_read /dev/pts/3\n",[28,2550,2551,2569],{"__ignoreMap":26},[68,2552,2553,2555,2558,2560,2563,2565,2567],{"class":70,"line":71},[68,2554,1004],{"class":74},[68,2556,2557],{"class":78}," demo3_async_serial_read.cpp",[68,2559,1010],{"class":122},[68,2561,2562],{"class":78}," demo3_async_serial_read",[68,2564,1016],{"class":122},[68,2566,1019],{"class":122},[68,2568,1022],{"class":122},[68,2570,2571,2574],{"class":70,"line":218},[68,2572,2573],{"class":74},"./demo3_async_serial_read",[68,2575,1030],{"class":78},[13,2577,2578],{},"终端 3：发送数据。",[20,2580,2582],{"className":62,"code":2581,"language":64,"meta":26,"style":26},"echo \"encoder 123\" > /dev/pts/4\n",[28,2583,2584],{"__ignoreMap":26},[68,2585,2586,2588,2591,2593],{"class":70,"line":71},[68,2587,1713],{"class":122},[68,2589,2590],{"class":78}," \"encoder 123\"",[68,2592,1719],{"class":211},[68,2594,991],{"class":78},[53,2596,1033],{"id":2597},"运行输出与时间顺序-2",[13,2599,2600],{},"程序立刻输出：",[20,2602,2605],{"className":2603,"code":2604,"language":25,"meta":26},[23],"main：注册 async_read_until\nmain：async_read_until 已返回，准备 io.run()\n",[28,2606,2604],{"__ignoreMap":26},[13,2608,2609,2610,2612],{},"程序卡在 ",[28,2611,1828],{},"。你发送数据后，程序输出：",[20,2614,2617],{"className":2615,"code":2616,"language":25,"meta":26},[23],"on_read_line：bytes_transferred = 12\non_read_line：收到一行 = encoder 123\nmain：io.run() 返回\n",[28,2618,2616],{"__ignoreMap":26},[13,2620,2621],{},"完整输出类似：",[20,2623,2626],{"className":2624,"code":2625,"language":25,"meta":26},[23],"main：注册 async_read_until\nmain：async_read_until 已返回，准备 io.run()\non_read_line：bytes_transferred = 12\non_read_line：收到一行 = encoder 123\nmain：io.run() 返回\n",[28,2627,2625],{"__ignoreMap":26},[53,2629,1056],{"id":2630},"本示例需要注意的点-2",[13,2632,2633,2635],{},[28,2634,1822],{}," 不阻塞。它只是注册读取任务。",[13,2637,2638],{},"如果你不调用：",[20,2640,2642],{"className":202,"code":2641,"language":204,"meta":26,"style":26},"io.run();\n",[28,2643,2644],{"__ignoreMap":26},[68,2645,2646,2649,2651],{"class":70,"line":71},[68,2647,2648],{"class":258},"io.",[68,2650,2469],{"class":74},[68,2652,2472],{"class":258},[13,2654,2655],{},"回调函数永远不会执行。",[53,2657,2658],{"id":2658},"回调参数说明",[13,2660,2661,2663],{},[28,2662,1822],{}," 的回调一般接收两个参数：",[20,2665,2667],{"className":202,"code":2666,"language":204,"meta":26,"style":26},"const boost::system::error_code& ec\nstd::size_t bytes_transferred\n",[28,2668,2669,2687],{"__ignoreMap":26},[68,2670,2671,2673,2675,2677,2679,2682,2684],{"class":70,"line":71},[68,2672,1902],{"class":211},[68,2674,797],{"class":74},[68,2676,380],{"class":258},[68,2678,420],{"class":74},[68,2680,2681],{"class":258},"::error_code",[68,2683,1553],{"class":211},[68,2685,2686],{"class":258}," ec\n",[68,2688,2689,2692,2694,2696],{"class":70,"line":218},[68,2690,2691],{"class":74},"std",[68,2693,380],{"class":258},[68,2695,789],{"class":211},[68,2697,2698],{"class":258}," bytes_transferred\n",[13,2700,2701],{},"所以绑定时用：",[20,2703,2705],{"className":202,"code":2704,"language":204,"meta":26,"style":26},"std::placeholders::_1\nstd::placeholders::_2\n",[28,2706,2707,2718],{"__ignoreMap":26},[68,2708,2709,2711,2713,2715],{"class":70,"line":71},[68,2710,2691],{"class":74},[68,2712,380],{"class":258},[68,2714,2402],{"class":74},[68,2716,2717],{"class":258},"::_1\n",[68,2719,2720,2722,2724,2726],{"class":70,"line":218},[68,2721,2691],{"class":74},[68,2723,380],{"class":258},[68,2725,2402],{"class":74},[68,2727,2728],{"class":258},"::_2\n",[13,2730,2731],{},"我们额外传了：",[20,2733,2735],{"className":202,"code":2734,"language":204,"meta":26,"style":26},"&buffer\n",[28,2736,2737],{"__ignoreMap":26},[68,2738,2739,2741],{"class":70,"line":71},[68,2740,1553],{"class":211},[68,2742,2743],{"class":258},"buffer\n",[13,2745,2746],{},"用于在回调里取出具体字符串。",[38,2748],{},[41,2750,2752],{"id":2751},"示例-4类里封装异步串口行读取","示例 4：类里封装异步串口行读取",[53,2754,178],{"id":2755},"程序目标-3",[13,2757,2758],{},"把异步串口读取封装成类。这个结构更接近真实机器人项目。",[13,2760,2761],{},"程序会连续读取多行串口数据，每收到一行就打印，然后继续注册下一次读取。",[53,2763,199],{"id":2764},"完整代码-3",[20,2766,2768],{"className":202,"code":2767,"language":204,"meta":26,"style":26},"#include \u003Cboost/asio.hpp>\n#include \u003Cboost/system/error_code.hpp>\n#include \u003Cfunctional>\n#include \u003Ciostream>\n#include \u003Cistream>\n#include \u003Cstring>\n\nclass SerialLineReader\n{\npublic:\n    SerialLineReader(boost::asio::io_context& io, const std::string& port_name)\n        : serial_(io)\n    {\n        boost::system::error_code ec;\n\n        serial_.open(port_name, ec);\n        if (ec)\n        {\n            std::cout \u003C\u003C \"打开串口失败：\" \u003C\u003C ec.message() \u003C\u003C std::endl;\n            return;\n        }\n\n        serial_.set_option(boost::asio::serial_port_base::baud_rate(115200));\n        serial_.set_option(boost::asio::serial_port_base::character_size(8));\n        serial_.set_option(boost::asio::serial_port_base::parity(\n            boost::asio::serial_port_base::parity::none));\n        serial_.set_option(boost::asio::serial_port_base::stop_bits(\n            boost::asio::serial_port_base::stop_bits::one));\n        serial_.set_option(boost::asio::serial_port_base::flow_control(\n            boost::asio::serial_port_base::flow_control::none));\n\n        std::cout \u003C\u003C \"SerialLineReader：串口打开成功，开始异步读取\" \u003C\u003C std::endl;\n\n        start_read();\n    }\n\nprivate:\n    void start_read()\n    {\n        boost::asio::async_read_until(serial_,\n                                      buffer_,\n                                      '\\n',\n                                      std::bind(&SerialLineReader::on_read,\n                                                this,\n                                                std::placeholders::_1,\n                                                std::placeholders::_2));\n    }\n\n    void on_read(const boost::system::error_code& ec, std::size_t bytes_transferred)\n    {\n        if (ec)\n        {\n            std::cout \u003C\u003C \"SerialLineReader::on_read 错误：\" \u003C\u003C ec.message() \u003C\u003C std::endl;\n            return;\n        }\n\n        std::istream is(&buffer_);\n        std::string line;\n        std::getline(is, line);\n\n        std::cout \u003C\u003C \"收到串口行，bytes = \" \u003C\u003C bytes_transferred\n                  \u003C\u003C \"，内容 = \" \u003C\u003C line \u003C\u003C std::endl;\n\n        start_read();\n    }\n\nprivate:\n    // serial_port 表示串口设备，后续读写都通过它完成。\n    boost::asio::serial_port serial_;\n    boost::asio::streambuf buffer_;\n};\n\nint main(int argc, char* argv[])\n{\n    // 程序从 main 函数开始执行，argc/argv 用来接收命令行参数。\n    std::string port_name = \"/dev/pts/3\";\n\n    if (argc >= 2)\n    {\n        port_name = argv[1];\n    }\n\n    // io_context 是 Asio 的事件循环对象，异步任务需要靠它调度。\n    boost::asio::io_context io;\n    SerialLineReader reader(io, port_name);\n\n    std::cout \u003C\u003C \"main：调用 io.run()，按 Ctrl+C 退出\" \u003C\u003C std::endl;\n\n    // 启动事件循环，前面注册的异步任务会在这里被调度执行。\n    io.run();\n\n    std::cout \u003C\u003C \"main：io.run() 返回\" \u003C\u003C std::endl;\n\n    return 0;\n}\n",[28,2769,2770,2776,2782,2788,2794,2800,2806,2810,2818,2822,2827,2868,2879,2883,2893,2897,2906,2913,2918,2943,2950,2955,2959,2987,3015,3039,3058,3082,3100,3124,3142,3146,3163,3167,3174,3178,3182,3187,3198,3202,3217,3222,3233,3252,3259,3270,3281,3285,3289,3326,3330,3336,3340,3365,3371,3375,3379,3394,3400,3410,3414,3429,3447,3451,3457,3461,3465,3469,3473,3484,3495,3500,3505,3526,3531,3536,3549,3554,3567,3572,3585,3590,3595,3600,3611,3623,3628,3646,3651,3656,3665,3670,3687,3692,3701],{"__ignoreMap":26},[68,2771,2772,2774],{"class":70,"line":71},[68,2773,212],{"class":211},[68,2775,215],{"class":78},[68,2777,2778,2780],{"class":70,"line":218},[68,2779,212],{"class":211},[68,2781,223],{"class":78},[68,2783,2784,2786],{"class":70,"line":226},[68,2785,212],{"class":211},[68,2787,1867],{"class":78},[68,2789,2790,2792],{"class":70,"line":234},[68,2791,212],{"class":211},[68,2793,231],{"class":78},[68,2795,2796,2798],{"class":70,"line":242},[68,2797,212],{"class":211},[68,2799,1184],{"class":78},[68,2801,2802,2804],{"class":70,"line":249},[68,2803,212],{"class":211},[68,2805,239],{"class":78},[68,2807,2808],{"class":70,"line":280},[68,2809,246],{"emptyLinePlaceholder":245},[68,2811,2812,2815],{"class":70,"line":286},[68,2813,2814],{"class":211},"class",[68,2816,2817],{"class":74}," SerialLineReader\n",[68,2819,2820],{"class":70,"line":293},[68,2821,283],{"class":258},[68,2823,2824],{"class":70,"line":311},[68,2825,2826],{"class":211},"public:\n",[68,2828,2829,2832,2834,2836,2838,2840,2842,2845,2847,2850,2852,2854,2856,2858,2861,2863,2866],{"class":70,"line":316},[68,2830,2831],{"class":74},"    SerialLineReader",[68,2833,259],{"class":258},[68,2835,550],{"class":74},[68,2837,380],{"class":258},[68,2839,383],{"class":74},[68,2841,380],{"class":258},[68,2843,2844],{"class":74},"io_context",[68,2846,1553],{"class":211},[68,2848,2849],{"class":264}," io",[68,2851,268],{"class":258},[68,2853,1902],{"class":211},[68,2855,453],{"class":74},[68,2857,380],{"class":258},[68,2859,2860],{"class":74},"string",[68,2862,1553],{"class":211},[68,2864,2865],{"class":264}," port_name",[68,2867,331],{"class":258},[68,2869,2870,2873,2876],{"class":70,"line":334},[68,2871,2872],{"class":258},"        : ",[68,2874,2875],{"class":74},"serial_",[68,2877,2878],{"class":258},"(io)\n",[68,2880,2881],{"class":70,"line":340},[68,2882,337],{"class":258},[68,2884,2885,2887,2889,2891],{"class":70,"line":357},[68,2886,636],{"class":74},[68,2888,380],{"class":258},[68,2890,420],{"class":74},[68,2892,423],{"class":258},[68,2894,2895],{"class":70,"line":363},[68,2896,246],{"emptyLinePlaceholder":245},[68,2898,2899,2902,2904],{"class":70,"line":368},[68,2900,2901],{"class":258},"        serial_.",[68,2903,470],{"class":74},[68,2905,473],{"class":258},[68,2907,2908,2911],{"class":70,"line":374},[68,2909,2910],{"class":211},"        if",[68,2912,481],{"class":258},[68,2914,2915],{"class":70,"line":389},[68,2916,2917],{"class":258},"        {\n",[68,2919,2920,2923,2925,2927,2929,2931,2933,2935,2937,2939,2941],{"class":70,"line":395},[68,2921,2922],{"class":74},"            std",[68,2924,436],{"class":258},[68,2926,439],{"class":211},[68,2928,499],{"class":78},[68,2930,445],{"class":211},[68,2932,504],{"class":258},[68,2934,507],{"class":74},[68,2936,510],{"class":258},[68,2938,439],{"class":211},[68,2940,453],{"class":74},[68,2942,456],{"class":258},[68,2944,2945,2948],{"class":70,"line":413},[68,2946,2947],{"class":211},"            return",[68,2949,308],{"class":258},[68,2951,2952],{"class":70,"line":426},[68,2953,2954],{"class":258},"        }\n",[68,2956,2957],{"class":70,"line":431},[68,2958,246],{"emptyLinePlaceholder":245},[68,2960,2961,2963,2965,2967,2969,2971,2973,2975,2977,2979,2981,2983,2985],{"class":70,"line":459},[68,2962,2901],{"class":258},[68,2964,545],{"class":74},[68,2966,259],{"class":258},[68,2968,550],{"class":74},[68,2970,380],{"class":258},[68,2972,383],{"class":74},[68,2974,380],{"class":258},[68,2976,559],{"class":74},[68,2978,380],{"class":258},[68,2980,564],{"class":74},[68,2982,259],{"class":258},[68,2984,569],{"class":122},[68,2986,572],{"class":258},[68,2988,2989,2991,2993,2995,2997,2999,3001,3003,3005,3007,3009,3011,3013],{"class":70,"line":464},[68,2990,2901],{"class":258},[68,2992,545],{"class":74},[68,2994,259],{"class":258},[68,2996,550],{"class":74},[68,2998,380],{"class":258},[68,3000,383],{"class":74},[68,3002,380],{"class":258},[68,3004,559],{"class":74},[68,3006,380],{"class":258},[68,3008,596],{"class":74},[68,3010,259],{"class":258},[68,3012,601],{"class":122},[68,3014,572],{"class":258},[68,3016,3017,3019,3021,3023,3025,3027,3029,3031,3033,3035,3037],{"class":70,"line":476},[68,3018,2901],{"class":258},[68,3020,545],{"class":74},[68,3022,259],{"class":258},[68,3024,550],{"class":74},[68,3026,380],{"class":258},[68,3028,383],{"class":74},[68,3030,380],{"class":258},[68,3032,559],{"class":74},[68,3034,380],{"class":258},[68,3036,627],{"class":74},[68,3038,630],{"class":258},[68,3040,3041,3044,3046,3048,3050,3052,3054,3056],{"class":70,"line":484},[68,3042,3043],{"class":74},"            boost",[68,3045,380],{"class":258},[68,3047,383],{"class":74},[68,3049,380],{"class":258},[68,3051,559],{"class":74},[68,3053,380],{"class":258},[68,3055,627],{"class":74},[68,3057,651],{"class":258},[68,3059,3060,3062,3064,3066,3068,3070,3072,3074,3076,3078,3080],{"class":70,"line":489},[68,3061,2901],{"class":258},[68,3063,545],{"class":74},[68,3065,259],{"class":258},[68,3067,550],{"class":74},[68,3069,380],{"class":258},[68,3071,383],{"class":74},[68,3073,380],{"class":258},[68,3075,559],{"class":74},[68,3077,380],{"class":258},[68,3079,675],{"class":74},[68,3081,630],{"class":258},[68,3083,3084,3086,3088,3090,3092,3094,3096,3098],{"class":70,"line":519},[68,3085,3043],{"class":74},[68,3087,380],{"class":258},[68,3089,383],{"class":74},[68,3091,380],{"class":258},[68,3093,559],{"class":74},[68,3095,380],{"class":258},[68,3097,675],{"class":74},[68,3099,697],{"class":258},[68,3101,3102,3104,3106,3108,3110,3112,3114,3116,3118,3120,3122],{"class":70,"line":530},[68,3103,2901],{"class":258},[68,3105,545],{"class":74},[68,3107,259],{"class":258},[68,3109,550],{"class":74},[68,3111,380],{"class":258},[68,3113,383],{"class":74},[68,3115,380],{"class":258},[68,3117,559],{"class":74},[68,3119,380],{"class":258},[68,3121,721],{"class":74},[68,3123,630],{"class":258},[68,3125,3126,3128,3130,3132,3134,3136,3138,3140],{"class":70,"line":535},[68,3127,3043],{"class":74},[68,3129,380],{"class":258},[68,3131,383],{"class":74},[68,3133,380],{"class":258},[68,3135,559],{"class":74},[68,3137,380],{"class":258},[68,3139,721],{"class":74},[68,3141,651],{"class":258},[68,3143,3144],{"class":70,"line":540},[68,3145,246],{"emptyLinePlaceholder":245},[68,3147,3148,3150,3152,3154,3157,3159,3161],{"class":70,"line":575},[68,3149,492],{"class":74},[68,3151,436],{"class":258},[68,3153,439],{"class":211},[68,3155,3156],{"class":78}," \"SerialLineReader：串口打开成功，开始异步读取\"",[68,3158,445],{"class":211},[68,3160,453],{"class":74},[68,3162,456],{"class":258},[68,3164,3165],{"class":70,"line":606},[68,3166,246],{"emptyLinePlaceholder":245},[68,3168,3169,3172],{"class":70,"line":633},[68,3170,3171],{"class":74},"        start_read",[68,3173,2472],{"class":258},[68,3175,3176],{"class":70,"line":654},[68,3177,360],{"class":258},[68,3179,3180],{"class":70,"line":680},[68,3181,246],{"emptyLinePlaceholder":245},[68,3183,3184],{"class":70,"line":700},[68,3185,3186],{"class":211},"private:\n",[68,3188,3189,3192,3195],{"class":70,"line":726},[68,3190,3191],{"class":211},"    void",[68,3193,3194],{"class":74}," start_read",[68,3196,3197],{"class":258},"()\n",[68,3199,3200],{"class":70,"line":745},[68,3201,337],{"class":258},[68,3203,3204,3206,3208,3210,3212,3214],{"class":70,"line":750},[68,3205,636],{"class":74},[68,3207,380],{"class":258},[68,3209,383],{"class":74},[68,3211,380],{"class":258},[68,3213,2356],{"class":74},[68,3215,3216],{"class":258},"(serial_,\n",[68,3218,3219],{"class":70,"line":771},[68,3220,3221],{"class":258},"                                      buffer_,\n",[68,3223,3224,3227,3229,3231],{"class":70,"line":776},[68,3225,3226],{"class":78},"                                      '",[68,3228,763],{"class":122},[68,3230,1480],{"class":78},[68,3232,1921],{"class":258},[68,3234,3235,3238,3240,3242,3244,3246,3249],{"class":70,"line":782},[68,3236,3237],{"class":74},"                                      std",[68,3239,380],{"class":258},[68,3241,2388],{"class":74},[68,3243,259],{"class":258},[68,3245,1553],{"class":211},[68,3247,3248],{"class":74},"SerialLineReader",[68,3250,3251],{"class":258},"::on_read,\n",[68,3253,3254,3257],{"class":70,"line":826},[68,3255,3256],{"class":122},"                                                this",[68,3258,1921],{"class":258},[68,3260,3261,3264,3266,3268],{"class":70,"line":833},[68,3262,3263],{"class":74},"                                                std",[68,3265,380],{"class":258},[68,3267,2402],{"class":74},[68,3269,2405],{"class":258},[68,3271,3272,3274,3276,3278],{"class":70,"line":838},[68,3273,3263],{"class":74},[68,3275,380],{"class":258},[68,3277,2402],{"class":74},[68,3279,3280],{"class":258},"::_2));\n",[68,3282,3283],{"class":70,"line":864},[68,3284,360],{"class":258},[68,3286,3287],{"class":70,"line":873},[68,3288,246],{"emptyLinePlaceholder":245},[68,3290,3291,3293,3296,3298,3300,3302,3304,3306,3308,3310,3312,3314,3316,3318,3320,3322,3324],{"class":70,"line":878},[68,3292,3191],{"class":211},[68,3294,3295],{"class":74}," on_read",[68,3297,259],{"class":258},[68,3299,1902],{"class":211},[68,3301,797],{"class":74},[68,3303,380],{"class":258},[68,3305,420],{"class":74},[68,3307,380],{"class":258},[68,3309,1913],{"class":74},[68,3311,1553],{"class":211},[68,3313,1918],{"class":264},[68,3315,268],{"class":258},[68,3317,2691],{"class":74},[68,3319,380],{"class":258},[68,3321,789],{"class":211},[68,3323,1933],{"class":264},[68,3325,331],{"class":258},[68,3327,3328],{"class":70,"line":883},[68,3329,337],{"class":258},[68,3331,3332,3334],{"class":70,"line":905},[68,3333,2910],{"class":211},[68,3335,481],{"class":258},[68,3337,3338],{"class":70,"line":923},[68,3339,2917],{"class":258},[68,3341,3342,3344,3346,3348,3351,3353,3355,3357,3359,3361,3363],{"class":70,"line":928},[68,3343,2922],{"class":74},[68,3345,436],{"class":258},[68,3347,439],{"class":211},[68,3349,3350],{"class":78}," \"SerialLineReader::on_read 错误：\"",[68,3352,445],{"class":211},[68,3354,504],{"class":258},[68,3356,507],{"class":74},[68,3358,510],{"class":258},[68,3360,439],{"class":211},[68,3362,453],{"class":74},[68,3364,456],{"class":258},[68,3366,3367,3369],{"class":70,"line":939},[68,3368,2947],{"class":211},[68,3370,308],{"class":258},[68,3372,3373],{"class":70,"line":2345},[68,3374,2954],{"class":258},[68,3376,3377],{"class":70,"line":2362},[68,3378,246],{"emptyLinePlaceholder":245},[68,3380,3381,3383,3385,3387,3389,3391],{"class":70,"line":2368},[68,3382,492],{"class":74},[68,3384,1545],{"class":258},[68,3386,1548],{"class":74},[68,3388,259],{"class":258},[68,3390,1553],{"class":211},[68,3392,3393],{"class":258},"buffer_);\n",[68,3395,3396,3398],{"class":70,"line":2380},[68,3397,492],{"class":74},[68,3399,1563],{"class":258},[68,3401,3402,3404,3406,3408],{"class":70,"line":2394},[68,3403,492],{"class":74},[68,3405,380],{"class":258},[68,3407,1572],{"class":74},[68,3409,1575],{"class":258},[68,3411,3412],{"class":70,"line":2408},[68,3413,246],{"emptyLinePlaceholder":245},[68,3415,3416,3418,3420,3422,3425,3427],{"class":70,"line":2420},[68,3417,492],{"class":74},[68,3419,436],{"class":258},[68,3421,439],{"class":211},[68,3423,3424],{"class":78}," \"收到串口行，bytes = \"",[68,3426,445],{"class":211},[68,3428,2698],{"class":258},[68,3430,3431,3434,3437,3439,3441,3443,3445],{"class":70,"line":2429},[68,3432,3433],{"class":211},"                  \u003C\u003C",[68,3435,3436],{"class":78}," \"，内容 = \"",[68,3438,445],{"class":211},[68,3440,1616],{"class":258},[68,3442,439],{"class":211},[68,3444,453],{"class":74},[68,3446,456],{"class":258},[68,3448,3449],{"class":70,"line":2434},[68,3450,246],{"emptyLinePlaceholder":245},[68,3452,3453,3455],{"class":70,"line":2452},[68,3454,3171],{"class":74},[68,3456,2472],{"class":258},[68,3458,3459],{"class":70,"line":2457},[68,3460,360],{"class":258},[68,3462,3463],{"class":70,"line":2463},[68,3464,246],{"emptyLinePlaceholder":245},[68,3466,3467],{"class":70,"line":2475},[68,3468,3186],{"class":211},[68,3470,3471],{"class":70,"line":2480},[68,3472,392],{"class":289},[68,3474,3475,3477,3479,3481],{"class":70,"line":2498},[68,3476,377],{"class":74},[68,3478,380],{"class":258},[68,3480,383],{"class":74},[68,3482,3483],{"class":258},"::serial_port serial_;\n",[68,3485,3486,3488,3490,3492],{"class":70,"line":2503},[68,3487,377],{"class":74},[68,3489,380],{"class":258},[68,3491,383],{"class":74},[68,3493,3494],{"class":258},"::streambuf buffer_;\n",[68,3496,3497],{"class":70,"line":2512},[68,3498,3499],{"class":258},"};\n",[68,3501,3503],{"class":70,"line":3502},72,[68,3504,246],{"emptyLinePlaceholder":245},[68,3506,3508,3510,3512,3514,3516,3518,3520,3522,3524],{"class":70,"line":3507},73,[68,3509,252],{"class":211},[68,3511,255],{"class":74},[68,3513,259],{"class":258},[68,3515,252],{"class":211},[68,3517,265],{"class":264},[68,3519,268],{"class":258},[68,3521,271],{"class":211},[68,3523,274],{"class":264},[68,3525,277],{"class":258},[68,3527,3529],{"class":70,"line":3528},74,[68,3530,283],{"class":258},[68,3532,3534],{"class":70,"line":3533},75,[68,3535,290],{"class":289},[68,3537,3539,3541,3543,3545,3547],{"class":70,"line":3538},76,[68,3540,296],{"class":74},[68,3542,299],{"class":258},[68,3544,302],{"class":211},[68,3546,305],{"class":78},[68,3548,308],{"class":258},[68,3550,3552],{"class":70,"line":3551},77,[68,3553,246],{"emptyLinePlaceholder":245},[68,3555,3557,3559,3561,3563,3565],{"class":70,"line":3556},78,[68,3558,319],{"class":211},[68,3560,322],{"class":258},[68,3562,325],{"class":211},[68,3564,328],{"class":122},[68,3566,331],{"class":258},[68,3568,3570],{"class":70,"line":3569},79,[68,3571,337],{"class":258},[68,3573,3575,3577,3579,3581,3583],{"class":70,"line":3574},80,[68,3576,343],{"class":258},[68,3578,302],{"class":211},[68,3580,348],{"class":258},[68,3582,351],{"class":122},[68,3584,354],{"class":258},[68,3586,3588],{"class":70,"line":3587},81,[68,3589,360],{"class":258},[68,3591,3593],{"class":70,"line":3592},82,[68,3594,246],{"emptyLinePlaceholder":245},[68,3596,3598],{"class":70,"line":3597},83,[68,3599,371],{"class":289},[68,3601,3603,3605,3607,3609],{"class":70,"line":3602},84,[68,3604,377],{"class":74},[68,3606,380],{"class":258},[68,3608,383],{"class":74},[68,3610,386],{"class":258},[68,3612,3614,3617,3620],{"class":70,"line":3613},85,[68,3615,3616],{"class":258},"    SerialLineReader ",[68,3618,3619],{"class":74},"reader",[68,3621,3622],{"class":258},"(io, port_name);\n",[68,3624,3626],{"class":70,"line":3625},86,[68,3627,246],{"emptyLinePlaceholder":245},[68,3629,3631,3633,3635,3637,3640,3642,3644],{"class":70,"line":3630},87,[68,3632,296],{"class":74},[68,3634,436],{"class":258},[68,3636,439],{"class":211},[68,3638,3639],{"class":78}," \"main：调用 io.run()，按 Ctrl+C 退出\"",[68,3641,445],{"class":211},[68,3643,453],{"class":74},[68,3645,456],{"class":258},[68,3647,3649],{"class":70,"line":3648},88,[68,3650,246],{"emptyLinePlaceholder":245},[68,3652,3654],{"class":70,"line":3653},89,[68,3655,2460],{"class":289},[68,3657,3659,3661,3663],{"class":70,"line":3658},90,[68,3660,2466],{"class":258},[68,3662,2469],{"class":74},[68,3664,2472],{"class":258},[68,3666,3668],{"class":70,"line":3667},91,[68,3669,246],{"emptyLinePlaceholder":245},[68,3671,3673,3675,3677,3679,3681,3683,3685],{"class":70,"line":3672},92,[68,3674,296],{"class":74},[68,3676,436],{"class":258},[68,3678,439],{"class":211},[68,3680,2489],{"class":78},[68,3682,445],{"class":211},[68,3684,453],{"class":74},[68,3686,456],{"class":258},[68,3688,3690],{"class":70,"line":3689},93,[68,3691,246],{"emptyLinePlaceholder":245},[68,3693,3695,3697,3699],{"class":70,"line":3694},94,[68,3696,931],{"class":211},[68,3698,934],{"class":122},[68,3700,308],{"class":258},[68,3702,3704],{"class":70,"line":3703},95,[68,3705,942],{"class":258},[13,3707,3708,949],{},[946,3709,948],{},[53,3711,952],{"id":3712},"编译运行-3",[13,3714,955],{},[20,3716,3717],{"className":62,"code":113,"language":64,"meta":26,"style":26},[28,3718,3719],{"__ignoreMap":26},[68,3720,3721,3723,3725,3727,3729,3731,3733],{"class":70,"line":71},[68,3722,50],{"class":74},[68,3724,123],{"class":122},[68,3726,123],{"class":122},[68,3728,128],{"class":78},[68,3730,131],{"class":122},[68,3732,128],{"class":78},[68,3734,136],{"class":122},[13,3736,1670],{},[20,3738,3740],{"className":62,"code":3739,"language":64,"meta":26,"style":26},"g++ demo4_serial_class_reader.cpp -o demo4_serial_class_reader -std=c++17 -lboost_system -pthread\n./demo4_serial_class_reader /dev/pts/3\n",[28,3741,3742,3760],{"__ignoreMap":26},[68,3743,3744,3746,3749,3751,3754,3756,3758],{"class":70,"line":71},[68,3745,1004],{"class":74},[68,3747,3748],{"class":78}," demo4_serial_class_reader.cpp",[68,3750,1010],{"class":122},[68,3752,3753],{"class":78}," demo4_serial_class_reader",[68,3755,1016],{"class":122},[68,3757,1019],{"class":122},[68,3759,1022],{"class":122},[68,3761,3762,3765],{"class":70,"line":218},[68,3763,3764],{"class":74},"./demo4_serial_class_reader",[68,3766,1030],{"class":78},[13,3768,3769],{},"终端 3：连续发送数据。",[20,3771,3773],{"className":62,"code":3772,"language":64,"meta":26,"style":26},"echo \"imu 1 2 3\" > /dev/pts/4\necho \"odom 0.1 0.2\" > /dev/pts/4\necho \"battery 24.1\" > /dev/pts/4\n",[28,3774,3775,3786,3797],{"__ignoreMap":26},[68,3776,3777,3779,3782,3784],{"class":70,"line":71},[68,3778,1713],{"class":122},[68,3780,3781],{"class":78}," \"imu 1 2 3\"",[68,3783,1719],{"class":211},[68,3785,991],{"class":78},[68,3787,3788,3790,3793,3795],{"class":70,"line":218},[68,3789,1713],{"class":122},[68,3791,3792],{"class":78}," \"odom 0.1 0.2\"",[68,3794,1719],{"class":211},[68,3796,991],{"class":78},[68,3798,3799,3801,3804,3806],{"class":70,"line":226},[68,3800,1713],{"class":122},[68,3802,3803],{"class":78}," \"battery 24.1\"",[68,3805,1719],{"class":211},[68,3807,991],{"class":78},[53,3809,1033],{"id":3810},"运行输出与时间顺序-3",[13,3812,3813],{},"程序启动后输出：",[20,3815,3818],{"className":3816,"code":3817,"language":25,"meta":26},[23],"SerialLineReader：串口打开成功，开始异步读取\nmain：调用 io.run()，按 Ctrl+C 退出\n",[28,3819,3817],{"__ignoreMap":26},[13,3821,3822],{},"每发送一行，程序打印一行：",[20,3824,3827],{"className":3825,"code":3826,"language":25,"meta":26},[23],"收到串口行，bytes = 10，内容 = imu 1 2 3\n收到串口行，bytes = 13，内容 = odom 0.1 0.2\n收到串口行，bytes = 13，内容 = battery 24.1\n",[28,3828,3826],{"__ignoreMap":26},[13,3830,3831,3832,36],{},"程序不会自动退出，因为每次收到一行后都会重新调用 ",[28,3833,3834],{},"start_read()",[53,3836,1056],{"id":3837},"本示例需要注意的点-3",[13,3839,3840],{},"这一句是连续读取的关键：",[20,3842,3844],{"className":202,"code":3843,"language":204,"meta":26,"style":26},"start_read();\n",[28,3845,3846],{"__ignoreMap":26},[68,3847,3848,3851],{"class":70,"line":71},[68,3849,3850],{"class":74},"start_read",[68,3852,2472],{"class":258},[13,3854,3855,3856,3859],{},"它在 ",[28,3857,3858],{},"on_read()"," 的最后再次注册下一次异步读取。",[13,3861,3862,3863,3865],{},"如果没有这句，程序只会读一行，然后 ",[28,3864,1828],{}," 就会返回。",[53,3867,3868],{"id":3868},"类成员变量生命周期说明",[20,3870,3872],{"className":202,"code":3871,"language":204,"meta":26,"style":26},"boost::asio::serial_port serial_;\nboost::asio::streambuf buffer_;\n",[28,3873,3874,3884],{"__ignoreMap":26},[68,3875,3876,3878,3880,3882],{"class":70,"line":71},[68,3877,550],{"class":74},[68,3879,380],{"class":258},[68,3881,383],{"class":74},[68,3883,3483],{"class":258},[68,3885,3886,3888,3890,3892],{"class":70,"line":218},[68,3887,550],{"class":74},[68,3889,380],{"class":258},[68,3891,383],{"class":74},[68,3893,3494],{"class":258},[13,3895,3896,3897,3900],{},"它们是类成员变量，生命周期和 ",[28,3898,3899],{},"SerialLineReader reader"," 一样长。",[13,3902,3903],{},"这比在局部函数里创建临时 buffer 更安全。",[53,3905,3906],{"id":3906},"成员函数绑定说明",[20,3908,3910],{"className":202,"code":3909,"language":204,"meta":26,"style":26},"std::bind(&SerialLineReader::on_read,\n          this,\n          std::placeholders::_1,\n          std::placeholders::_2)\n",[28,3911,3912,3928,3935,3946],{"__ignoreMap":26},[68,3913,3914,3916,3918,3920,3922,3924,3926],{"class":70,"line":71},[68,3915,2691],{"class":74},[68,3917,380],{"class":258},[68,3919,2388],{"class":74},[68,3921,259],{"class":258},[68,3923,1553],{"class":211},[68,3925,3248],{"class":74},[68,3927,3251],{"class":258},[68,3929,3930,3933],{"class":70,"line":218},[68,3931,3932],{"class":122},"          this",[68,3934,1921],{"class":258},[68,3936,3937,3940,3942,3944],{"class":70,"line":226},[68,3938,3939],{"class":74},"          std",[68,3941,380],{"class":258},[68,3943,2402],{"class":74},[68,3945,2405],{"class":258},[68,3947,3948,3950,3952,3954],{"class":70,"line":234},[68,3949,3939],{"class":74},[68,3951,380],{"class":258},[68,3953,2402],{"class":74},[68,3955,3956],{"class":258},"::_2)\n",[13,3958,3959],{},"表示异步读取完成后调用：",[20,3961,3963],{"className":202,"code":3962,"language":204,"meta":26,"style":26},"this->on_read(ec, bytes_transferred);\n",[28,3964,3965],{"__ignoreMap":26},[68,3966,3967,3970,3973,3976],{"class":70,"line":71},[68,3968,3969],{"class":122},"this",[68,3971,3972],{"class":258},"->",[68,3974,3975],{"class":74},"on_read",[68,3977,3978],{"class":258},"(ec, bytes_transferred);\n",[38,3980],{},[41,3982,3984],{"id":3983},"示例-5类里封装异步串口写队列","示例 5：类里封装异步串口写队列",[53,3986,178],{"id":3987},"程序目标-4",[13,3989,3990],{},"真实机器人上位机经常需要连续给下位机发命令，例如：",[20,3992,3995],{"className":3993,"code":3994,"language":25,"meta":26},[23],"cmd_vel 0.2 0.0\ncmd_vel 0.2 0.1\ncmd_vel 0.0 0.0\n",[28,3996,3994],{"__ignoreMap":26},[13,3998,3999,4000,4003],{},"异步写时不能随便多个 ",[28,4001,4002],{},"async_write()"," 同时写同一个串口。更稳的做法是写队列：",[20,4005,4008],{"className":4006,"code":4007,"language":25,"meta":26},[23],"如果当前没有写操作，就开始写\n如果正在写，就先放入队列\n当前写完后，再写下一条\n",[28,4009,4007],{"__ignoreMap":26},[53,4011,199],{"id":4012},"完整代码-4",[20,4014,4016],{"className":202,"code":4015,"language":204,"meta":26,"style":26},"#include \u003Cboost/asio.hpp>\n#include \u003Cboost/system/error_code.hpp>\n#include \u003Cdeque>\n#include \u003Cfunctional>\n#include \u003Ciostream>\n#include \u003Cstring>\n\nclass SerialWriter\n{\npublic:\n    SerialWriter(boost::asio::io_context& io, const std::string& port_name)\n        : serial_(io)\n    {\n        boost::system::error_code ec;\n        serial_.open(port_name, ec);\n        if (ec)\n        {\n            std::cout \u003C\u003C \"打开串口失败：\" \u003C\u003C ec.message() \u003C\u003C std::endl;\n            return;\n        }\n\n        serial_.set_option(boost::asio::serial_port_base::baud_rate(115200));\n        std::cout \u003C\u003C \"SerialWriter：串口打开成功\" \u003C\u003C std::endl;\n    }\n\n    void async_send(const std::string& msg)\n    {\n        bool writing = !write_queue_.empty();\n\n        write_queue_.push_back(msg);\n\n        std::cout \u003C\u003C \"加入发送队列：\" \u003C\u003C msg;\n\n        if (!writing)\n        {\n            do_write();\n        }\n    }\n\nprivate:\n    void do_write()\n    {\n        // 注册异步写入，写完后由回调通知结果。\n        boost::asio::async_write(serial_,\n                                 boost::asio::buffer(write_queue_.front()),\n                                 std::bind(&SerialWriter::on_write,\n                                           this,\n                                           std::placeholders::_1,\n                                           std::placeholders::_2));\n    }\n\n    void on_write(const boost::system::error_code& ec, std::size_t bytes_transferred)\n    {\n        if (ec)\n        {\n            std::cout \u003C\u003C \"发送失败：\" \u003C\u003C ec.message() \u003C\u003C std::endl;\n            return;\n        }\n\n        std::cout \u003C\u003C \"发送完成，字节数 = \" \u003C\u003C bytes_transferred \u003C\u003C std::endl;\n\n        write_queue_.pop_front();\n\n        if (!write_queue_.empty())\n        {\n            do_write();\n        }\n    }\n\nprivate:\n    boost::asio::serial_port serial_;\n    std::deque\u003Cstd::string> write_queue_;\n};\n\nint main(int argc, char* argv[])\n{\n    // 程序从 main 函数开始执行，argc/argv 用来接收命令行参数。\n    std::string port_name = \"/dev/pts/3\";\n\n    if (argc >= 2)\n    {\n        port_name = argv[1];\n    }\n\n    // io_context 是 Asio 的事件循环对象，异步任务需要靠它调度。\n    boost::asio::io_context io;\n    SerialWriter writer(io, port_name);\n\n    writer.async_send(\"cmd_vel 0.2 0.0\\n\");\n    writer.async_send(\"cmd_vel 0.2 0.1\\n\");\n    writer.async_send(\"cmd_vel 0.0 0.0\\n\");\n\n    // 启动事件循环，前面注册的异步任务会在这里被调度执行。\n    io.run();\n\n    std::cout \u003C\u003C \"main：发送队列清空，程序结束\" \u003C\u003C std::endl;\n\n    return 0;\n}\n",[28,4017,4018,4024,4030,4037,4043,4049,4055,4059,4066,4070,4074,4111,4119,4123,4133,4141,4147,4151,4175,4181,4185,4189,4217,4234,4238,4242,4266,4270,4291,4295,4306,4310,4326,4330,4343,4347,4354,4358,4362,4366,4370,4379,4383,4388,4403,4425,4444,4451,4462,4472,4476,4480,4517,4521,4527,4531,4555,4561,4565,4569,4590,4594,4603,4607,4622,4626,4632,4636,4640,4644,4648,4658,4679,4683,4687,4707,4711,4715,4727,4731,4743,4747,4759,4763,4767,4771,4781,4791,4795,4815,4832,4849,4853,4857,4865,4869,4887,4892,4901],{"__ignoreMap":26},[68,4019,4020,4022],{"class":70,"line":71},[68,4021,212],{"class":211},[68,4023,215],{"class":78},[68,4025,4026,4028],{"class":70,"line":218},[68,4027,212],{"class":211},[68,4029,223],{"class":78},[68,4031,4032,4034],{"class":70,"line":226},[68,4033,212],{"class":211},[68,4035,4036],{"class":78}," \u003Cdeque>\n",[68,4038,4039,4041],{"class":70,"line":234},[68,4040,212],{"class":211},[68,4042,1867],{"class":78},[68,4044,4045,4047],{"class":70,"line":242},[68,4046,212],{"class":211},[68,4048,231],{"class":78},[68,4050,4051,4053],{"class":70,"line":249},[68,4052,212],{"class":211},[68,4054,239],{"class":78},[68,4056,4057],{"class":70,"line":280},[68,4058,246],{"emptyLinePlaceholder":245},[68,4060,4061,4063],{"class":70,"line":286},[68,4062,2814],{"class":211},[68,4064,4065],{"class":74}," SerialWriter\n",[68,4067,4068],{"class":70,"line":293},[68,4069,283],{"class":258},[68,4071,4072],{"class":70,"line":311},[68,4073,2826],{"class":211},[68,4075,4076,4079,4081,4083,4085,4087,4089,4091,4093,4095,4097,4099,4101,4103,4105,4107,4109],{"class":70,"line":316},[68,4077,4078],{"class":74},"    SerialWriter",[68,4080,259],{"class":258},[68,4082,550],{"class":74},[68,4084,380],{"class":258},[68,4086,383],{"class":74},[68,4088,380],{"class":258},[68,4090,2844],{"class":74},[68,4092,1553],{"class":211},[68,4094,2849],{"class":264},[68,4096,268],{"class":258},[68,4098,1902],{"class":211},[68,4100,453],{"class":74},[68,4102,380],{"class":258},[68,4104,2860],{"class":74},[68,4106,1553],{"class":211},[68,4108,2865],{"class":264},[68,4110,331],{"class":258},[68,4112,4113,4115,4117],{"class":70,"line":334},[68,4114,2872],{"class":258},[68,4116,2875],{"class":74},[68,4118,2878],{"class":258},[68,4120,4121],{"class":70,"line":340},[68,4122,337],{"class":258},[68,4124,4125,4127,4129,4131],{"class":70,"line":357},[68,4126,636],{"class":74},[68,4128,380],{"class":258},[68,4130,420],{"class":74},[68,4132,423],{"class":258},[68,4134,4135,4137,4139],{"class":70,"line":363},[68,4136,2901],{"class":258},[68,4138,470],{"class":74},[68,4140,473],{"class":258},[68,4142,4143,4145],{"class":70,"line":368},[68,4144,2910],{"class":211},[68,4146,481],{"class":258},[68,4148,4149],{"class":70,"line":374},[68,4150,2917],{"class":258},[68,4152,4153,4155,4157,4159,4161,4163,4165,4167,4169,4171,4173],{"class":70,"line":389},[68,4154,2922],{"class":74},[68,4156,436],{"class":258},[68,4158,439],{"class":211},[68,4160,499],{"class":78},[68,4162,445],{"class":211},[68,4164,504],{"class":258},[68,4166,507],{"class":74},[68,4168,510],{"class":258},[68,4170,439],{"class":211},[68,4172,453],{"class":74},[68,4174,456],{"class":258},[68,4176,4177,4179],{"class":70,"line":395},[68,4178,2947],{"class":211},[68,4180,308],{"class":258},[68,4182,4183],{"class":70,"line":413},[68,4184,2954],{"class":258},[68,4186,4187],{"class":70,"line":426},[68,4188,246],{"emptyLinePlaceholder":245},[68,4190,4191,4193,4195,4197,4199,4201,4203,4205,4207,4209,4211,4213,4215],{"class":70,"line":431},[68,4192,2901],{"class":258},[68,4194,545],{"class":74},[68,4196,259],{"class":258},[68,4198,550],{"class":74},[68,4200,380],{"class":258},[68,4202,383],{"class":74},[68,4204,380],{"class":258},[68,4206,559],{"class":74},[68,4208,380],{"class":258},[68,4210,564],{"class":74},[68,4212,259],{"class":258},[68,4214,569],{"class":122},[68,4216,572],{"class":258},[68,4218,4219,4221,4223,4225,4228,4230,4232],{"class":70,"line":459},[68,4220,492],{"class":74},[68,4222,436],{"class":258},[68,4224,439],{"class":211},[68,4226,4227],{"class":78}," \"SerialWriter：串口打开成功\"",[68,4229,445],{"class":211},[68,4231,453],{"class":74},[68,4233,456],{"class":258},[68,4235,4236],{"class":70,"line":464},[68,4237,360],{"class":258},[68,4239,4240],{"class":70,"line":476},[68,4241,246],{"emptyLinePlaceholder":245},[68,4243,4244,4246,4249,4251,4253,4255,4257,4259,4261,4264],{"class":70,"line":484},[68,4245,3191],{"class":211},[68,4247,4248],{"class":74}," async_send",[68,4250,259],{"class":258},[68,4252,1902],{"class":211},[68,4254,453],{"class":74},[68,4256,380],{"class":258},[68,4258,2860],{"class":74},[68,4260,1553],{"class":211},[68,4262,4263],{"class":264}," msg",[68,4265,331],{"class":258},[68,4267,4268],{"class":70,"line":489},[68,4269,337],{"class":258},[68,4271,4272,4275,4278,4280,4283,4286,4289],{"class":70,"line":519},[68,4273,4274],{"class":211},"        bool",[68,4276,4277],{"class":258}," writing ",[68,4279,302],{"class":211},[68,4281,4282],{"class":211}," !",[68,4284,4285],{"class":258},"write_queue_.",[68,4287,4288],{"class":74},"empty",[68,4290,2472],{"class":258},[68,4292,4293],{"class":70,"line":530},[68,4294,246],{"emptyLinePlaceholder":245},[68,4296,4297,4300,4303],{"class":70,"line":535},[68,4298,4299],{"class":258},"        write_queue_.",[68,4301,4302],{"class":74},"push_back",[68,4304,4305],{"class":258},"(msg);\n",[68,4307,4308],{"class":70,"line":540},[68,4309,246],{"emptyLinePlaceholder":245},[68,4311,4312,4314,4316,4318,4321,4323],{"class":70,"line":575},[68,4313,492],{"class":74},[68,4315,436],{"class":258},[68,4317,439],{"class":211},[68,4319,4320],{"class":78}," \"加入发送队列：\"",[68,4322,445],{"class":211},[68,4324,4325],{"class":258}," msg;\n",[68,4327,4328],{"class":70,"line":606},[68,4329,246],{"emptyLinePlaceholder":245},[68,4331,4332,4334,4337,4340],{"class":70,"line":633},[68,4333,2910],{"class":211},[68,4335,4336],{"class":258}," (",[68,4338,4339],{"class":211},"!",[68,4341,4342],{"class":258},"writing)\n",[68,4344,4345],{"class":70,"line":654},[68,4346,2917],{"class":258},[68,4348,4349,4352],{"class":70,"line":680},[68,4350,4351],{"class":74},"            do_write",[68,4353,2472],{"class":258},[68,4355,4356],{"class":70,"line":700},[68,4357,2954],{"class":258},[68,4359,4360],{"class":70,"line":726},[68,4361,360],{"class":258},[68,4363,4364],{"class":70,"line":745},[68,4365,246],{"emptyLinePlaceholder":245},[68,4367,4368],{"class":70,"line":750},[68,4369,3186],{"class":211},[68,4371,4372,4374,4377],{"class":70,"line":771},[68,4373,3191],{"class":211},[68,4375,4376],{"class":74}," do_write",[68,4378,3197],{"class":258},[68,4380,4381],{"class":70,"line":776},[68,4382,337],{"class":258},[68,4384,4385],{"class":70,"line":782},[68,4386,4387],{"class":289},"        // 注册异步写入，写完后由回调通知结果。\n",[68,4389,4390,4392,4394,4396,4398,4401],{"class":70,"line":826},[68,4391,636],{"class":74},[68,4393,380],{"class":258},[68,4395,383],{"class":74},[68,4397,380],{"class":258},[68,4399,4400],{"class":74},"async_write",[68,4402,3216],{"class":258},[68,4404,4405,4408,4410,4412,4414,4416,4419,4422],{"class":70,"line":833},[68,4406,4407],{"class":74},"                                 boost",[68,4409,380],{"class":258},[68,4411,383],{"class":74},[68,4413,380],{"class":258},[68,4415,820],{"class":74},[68,4417,4418],{"class":258},"(write_queue_.",[68,4420,4421],{"class":74},"front",[68,4423,4424],{"class":258},"()),\n",[68,4426,4427,4430,4432,4434,4436,4438,4441],{"class":70,"line":838},[68,4428,4429],{"class":74},"                                 std",[68,4431,380],{"class":258},[68,4433,2388],{"class":74},[68,4435,259],{"class":258},[68,4437,1553],{"class":211},[68,4439,4440],{"class":74},"SerialWriter",[68,4442,4443],{"class":258},"::on_write,\n",[68,4445,4446,4449],{"class":70,"line":864},[68,4447,4448],{"class":122},"                                           this",[68,4450,1921],{"class":258},[68,4452,4453,4456,4458,4460],{"class":70,"line":873},[68,4454,4455],{"class":74},"                                           std",[68,4457,380],{"class":258},[68,4459,2402],{"class":74},[68,4461,2405],{"class":258},[68,4463,4464,4466,4468,4470],{"class":70,"line":878},[68,4465,4455],{"class":74},[68,4467,380],{"class":258},[68,4469,2402],{"class":74},[68,4471,3280],{"class":258},[68,4473,4474],{"class":70,"line":883},[68,4475,360],{"class":258},[68,4477,4478],{"class":70,"line":905},[68,4479,246],{"emptyLinePlaceholder":245},[68,4481,4482,4484,4487,4489,4491,4493,4495,4497,4499,4501,4503,4505,4507,4509,4511,4513,4515],{"class":70,"line":923},[68,4483,3191],{"class":211},[68,4485,4486],{"class":74}," on_write",[68,4488,259],{"class":258},[68,4490,1902],{"class":211},[68,4492,797],{"class":74},[68,4494,380],{"class":258},[68,4496,420],{"class":74},[68,4498,380],{"class":258},[68,4500,1913],{"class":74},[68,4502,1553],{"class":211},[68,4504,1918],{"class":264},[68,4506,268],{"class":258},[68,4508,2691],{"class":74},[68,4510,380],{"class":258},[68,4512,789],{"class":211},[68,4514,1933],{"class":264},[68,4516,331],{"class":258},[68,4518,4519],{"class":70,"line":928},[68,4520,337],{"class":258},[68,4522,4523,4525],{"class":70,"line":939},[68,4524,2910],{"class":211},[68,4526,481],{"class":258},[68,4528,4529],{"class":70,"line":2345},[68,4530,2917],{"class":258},[68,4532,4533,4535,4537,4539,4541,4543,4545,4547,4549,4551,4553],{"class":70,"line":2362},[68,4534,2922],{"class":74},[68,4536,436],{"class":258},[68,4538,439],{"class":211},[68,4540,847],{"class":78},[68,4542,445],{"class":211},[68,4544,504],{"class":258},[68,4546,507],{"class":74},[68,4548,510],{"class":258},[68,4550,439],{"class":211},[68,4552,453],{"class":74},[68,4554,456],{"class":258},[68,4556,4557,4559],{"class":70,"line":2368},[68,4558,2947],{"class":211},[68,4560,308],{"class":258},[68,4562,4563],{"class":70,"line":2380},[68,4564,2954],{"class":258},[68,4566,4567],{"class":70,"line":2394},[68,4568,246],{"emptyLinePlaceholder":245},[68,4570,4571,4573,4575,4577,4580,4582,4584,4586,4588],{"class":70,"line":2408},[68,4572,492],{"class":74},[68,4574,436],{"class":258},[68,4576,439],{"class":211},[68,4578,4579],{"class":78}," \"发送完成，字节数 = \"",[68,4581,445],{"class":211},[68,4583,2056],{"class":258},[68,4585,439],{"class":211},[68,4587,453],{"class":74},[68,4589,456],{"class":258},[68,4591,4592],{"class":70,"line":2420},[68,4593,246],{"emptyLinePlaceholder":245},[68,4595,4596,4598,4601],{"class":70,"line":2429},[68,4597,4299],{"class":258},[68,4599,4600],{"class":74},"pop_front",[68,4602,2472],{"class":258},[68,4604,4605],{"class":70,"line":2434},[68,4606,246],{"emptyLinePlaceholder":245},[68,4608,4609,4611,4613,4615,4617,4619],{"class":70,"line":2452},[68,4610,2910],{"class":211},[68,4612,4336],{"class":258},[68,4614,4339],{"class":211},[68,4616,4285],{"class":258},[68,4618,4288],{"class":74},[68,4620,4621],{"class":258},"())\n",[68,4623,4624],{"class":70,"line":2457},[68,4625,2917],{"class":258},[68,4627,4628,4630],{"class":70,"line":2463},[68,4629,4351],{"class":74},[68,4631,2472],{"class":258},[68,4633,4634],{"class":70,"line":2475},[68,4635,2954],{"class":258},[68,4637,4638],{"class":70,"line":2480},[68,4639,360],{"class":258},[68,4641,4642],{"class":70,"line":2498},[68,4643,246],{"emptyLinePlaceholder":245},[68,4645,4646],{"class":70,"line":2503},[68,4647,3186],{"class":211},[68,4649,4650,4652,4654,4656],{"class":70,"line":2512},[68,4651,377],{"class":74},[68,4653,380],{"class":258},[68,4655,383],{"class":74},[68,4657,3483],{"class":258},[68,4659,4660,4662,4665,4668,4670,4673,4676],{"class":70,"line":3502},[68,4661,296],{"class":74},[68,4663,4664],{"class":258},"::deque",[68,4666,4667],{"class":211},"\u003C",[68,4669,2691],{"class":74},[68,4671,4672],{"class":258},"::string",[68,4674,4675],{"class":211},">",[68,4677,4678],{"class":258}," write_queue_;\n",[68,4680,4681],{"class":70,"line":3507},[68,4682,3499],{"class":258},[68,4684,4685],{"class":70,"line":3528},[68,4686,246],{"emptyLinePlaceholder":245},[68,4688,4689,4691,4693,4695,4697,4699,4701,4703,4705],{"class":70,"line":3533},[68,4690,252],{"class":211},[68,4692,255],{"class":74},[68,4694,259],{"class":258},[68,4696,252],{"class":211},[68,4698,265],{"class":264},[68,4700,268],{"class":258},[68,4702,271],{"class":211},[68,4704,274],{"class":264},[68,4706,277],{"class":258},[68,4708,4709],{"class":70,"line":3538},[68,4710,283],{"class":258},[68,4712,4713],{"class":70,"line":3551},[68,4714,290],{"class":289},[68,4716,4717,4719,4721,4723,4725],{"class":70,"line":3556},[68,4718,296],{"class":74},[68,4720,299],{"class":258},[68,4722,302],{"class":211},[68,4724,305],{"class":78},[68,4726,308],{"class":258},[68,4728,4729],{"class":70,"line":3569},[68,4730,246],{"emptyLinePlaceholder":245},[68,4732,4733,4735,4737,4739,4741],{"class":70,"line":3574},[68,4734,319],{"class":211},[68,4736,322],{"class":258},[68,4738,325],{"class":211},[68,4740,328],{"class":122},[68,4742,331],{"class":258},[68,4744,4745],{"class":70,"line":3587},[68,4746,337],{"class":258},[68,4748,4749,4751,4753,4755,4757],{"class":70,"line":3592},[68,4750,343],{"class":258},[68,4752,302],{"class":211},[68,4754,348],{"class":258},[68,4756,351],{"class":122},[68,4758,354],{"class":258},[68,4760,4761],{"class":70,"line":3597},[68,4762,360],{"class":258},[68,4764,4765],{"class":70,"line":3602},[68,4766,246],{"emptyLinePlaceholder":245},[68,4768,4769],{"class":70,"line":3613},[68,4770,371],{"class":289},[68,4772,4773,4775,4777,4779],{"class":70,"line":3625},[68,4774,377],{"class":74},[68,4776,380],{"class":258},[68,4778,383],{"class":74},[68,4780,386],{"class":258},[68,4782,4783,4786,4789],{"class":70,"line":3630},[68,4784,4785],{"class":258},"    SerialWriter ",[68,4787,4788],{"class":74},"writer",[68,4790,3622],{"class":258},[68,4792,4793],{"class":70,"line":3648},[68,4794,246],{"emptyLinePlaceholder":245},[68,4796,4797,4800,4803,4805,4808,4810,4812],{"class":70,"line":3653},[68,4798,4799],{"class":258},"    writer.",[68,4801,4802],{"class":74},"async_send",[68,4804,259],{"class":258},[68,4806,4807],{"class":78},"\"cmd_vel 0.2 0.0",[68,4809,763],{"class":122},[68,4811,766],{"class":78},[68,4813,4814],{"class":258},");\n",[68,4816,4817,4819,4821,4823,4826,4828,4830],{"class":70,"line":3658},[68,4818,4799],{"class":258},[68,4820,4802],{"class":74},[68,4822,259],{"class":258},[68,4824,4825],{"class":78},"\"cmd_vel 0.2 0.1",[68,4827,763],{"class":122},[68,4829,766],{"class":78},[68,4831,4814],{"class":258},[68,4833,4834,4836,4838,4840,4843,4845,4847],{"class":70,"line":3667},[68,4835,4799],{"class":258},[68,4837,4802],{"class":74},[68,4839,259],{"class":258},[68,4841,4842],{"class":78},"\"cmd_vel 0.0 0.0",[68,4844,763],{"class":122},[68,4846,766],{"class":78},[68,4848,4814],{"class":258},[68,4850,4851],{"class":70,"line":3672},[68,4852,246],{"emptyLinePlaceholder":245},[68,4854,4855],{"class":70,"line":3689},[68,4856,2460],{"class":289},[68,4858,4859,4861,4863],{"class":70,"line":3694},[68,4860,2466],{"class":258},[68,4862,2469],{"class":74},[68,4864,2472],{"class":258},[68,4866,4867],{"class":70,"line":3703},[68,4868,246],{"emptyLinePlaceholder":245},[68,4870,4872,4874,4876,4878,4881,4883,4885],{"class":70,"line":4871},96,[68,4873,296],{"class":74},[68,4875,436],{"class":258},[68,4877,439],{"class":211},[68,4879,4880],{"class":78}," \"main：发送队列清空，程序结束\"",[68,4882,445],{"class":211},[68,4884,453],{"class":74},[68,4886,456],{"class":258},[68,4888,4890],{"class":70,"line":4889},97,[68,4891,246],{"emptyLinePlaceholder":245},[68,4893,4895,4897,4899],{"class":70,"line":4894},98,[68,4896,931],{"class":211},[68,4898,934],{"class":122},[68,4900,308],{"class":258},[68,4902,4904],{"class":70,"line":4903},99,[68,4905,942],{"class":258},[13,4907,4908,949],{},[946,4909,948],{},[53,4911,952],{"id":4912},"编译运行-4",[13,4914,955],{},[20,4916,4917],{"className":62,"code":113,"language":64,"meta":26,"style":26},[28,4918,4919],{"__ignoreMap":26},[68,4920,4921,4923,4925,4927,4929,4931,4933],{"class":70,"line":71},[68,4922,50],{"class":74},[68,4924,123],{"class":122},[68,4926,123],{"class":122},[68,4928,128],{"class":78},[68,4930,131],{"class":122},[68,4932,128],{"class":78},[68,4934,136],{"class":122},[13,4936,978],{},[20,4938,4939],{"className":62,"code":981,"language":64,"meta":26,"style":26},[28,4940,4941],{"__ignoreMap":26},[68,4942,4943,4945],{"class":70,"line":71},[68,4944,988],{"class":74},[68,4946,991],{"class":78},[13,4948,4949],{},"终端 3：运行程序。",[20,4951,4953],{"className":62,"code":4952,"language":64,"meta":26,"style":26},"g++ demo5_serial_write_queue.cpp -o demo5_serial_write_queue -std=c++17 -lboost_system -pthread\n./demo5_serial_write_queue /dev/pts/3\n",[28,4954,4955,4973],{"__ignoreMap":26},[68,4956,4957,4959,4962,4964,4967,4969,4971],{"class":70,"line":71},[68,4958,1004],{"class":74},[68,4960,4961],{"class":78}," demo5_serial_write_queue.cpp",[68,4963,1010],{"class":122},[68,4965,4966],{"class":78}," demo5_serial_write_queue",[68,4968,1016],{"class":122},[68,4970,1019],{"class":122},[68,4972,1022],{"class":122},[68,4974,4975,4978],{"class":70,"line":218},[68,4976,4977],{"class":74},"./demo5_serial_write_queue",[68,4979,1030],{"class":78},[53,4981,1033],{"id":4982},"运行输出与时间顺序-4",[13,4984,4985],{},"程序终端输出类似：",[20,4987,4990],{"className":4988,"code":4989,"language":25,"meta":26},[23],"SerialWriter：串口打开成功\n加入发送队列：cmd_vel 0.2 0.0\n加入发送队列：cmd_vel 0.2 0.1\n加入发送队列：cmd_vel 0.0 0.0\n发送完成，字节数 = 16\n发送完成，字节数 = 16\n发送完成，字节数 = 16\nmain：发送队列清空，程序结束\n",[28,4991,4989],{"__ignoreMap":26},[13,4993,1045],{},[20,4995,4997],{"className":4996,"code":3994,"language":25,"meta":26},[23],[28,4998,3994],{"__ignoreMap":26},[53,5000,1056],{"id":5001},"本示例需要注意的点-4",[13,5003,5004,5005,5008],{},"这里不能把 ",[28,5006,5007],{},"msg"," 做成临时局部变量后立刻异步写，因为异步写可能还没完成，数据已经销毁。",[13,5010,5011],{},"本例用：",[20,5013,5015],{"className":202,"code":5014,"language":204,"meta":26,"style":26},"std::deque\u003Cstd::string> write_queue_;\n",[28,5016,5017],{"__ignoreMap":26},[68,5018,5019,5021,5023,5025,5027,5029,5031],{"class":70,"line":71},[68,5020,2691],{"class":74},[68,5022,4664],{"class":258},[68,5024,4667],{"class":211},[68,5026,2691],{"class":74},[68,5028,4672],{"class":258},[68,5030,4675],{"class":211},[68,5032,4678],{"class":258},[13,5034,5035],{},"保存待发送数据，保证 buffer 指向的字符串在写完成之前一直存在。",[53,5037,5039,5041],{"id":5038},"async_write-说明",[28,5040,4002],{}," 说明",[20,5043,5045],{"className":202,"code":5044,"language":204,"meta":26,"style":26},"boost::asio::async_write(serial_, buffer, handler);\n",[28,5046,5047],{"__ignoreMap":26},[68,5048,5049,5051,5053,5055,5057,5059],{"class":70,"line":71},[68,5050,550],{"class":74},[68,5052,380],{"class":258},[68,5054,383],{"class":74},[68,5056,380],{"class":258},[68,5058,4400],{"class":74},[68,5060,5061],{"class":258},"(serial_, buffer, handler);\n",[13,5063,5064],{},"作用：异步写完整个 buffer。",[13,5066,5067],{},"回调参数：",[20,5069,5070],{"className":202,"code":2666,"language":204,"meta":26,"style":26},[28,5071,5072,5088],{"__ignoreMap":26},[68,5073,5074,5076,5078,5080,5082,5084,5086],{"class":70,"line":71},[68,5075,1902],{"class":211},[68,5077,797],{"class":74},[68,5079,380],{"class":258},[68,5081,420],{"class":74},[68,5083,2681],{"class":258},[68,5085,1553],{"class":211},[68,5087,2686],{"class":258},[68,5089,5090,5092,5094,5096],{"class":70,"line":218},[68,5091,2691],{"class":74},[68,5093,380],{"class":258},[68,5095,789],{"class":211},[68,5097,2698],{"class":258},[13,5099,5100,5101,36],{},"返回值：",[28,5102,1894],{},[38,5104],{},[41,5106,5107],{"id":5107},"本节总结",[1815,5109,5110,5113,5119,5124,5131,5134],{},[1818,5111,5112],{},"同步串口读写简单，但会阻塞。",[1818,5114,5115,5116,5118],{},"异步串口读写需要 ",[28,5117,1828],{}," 驱动。",[1818,5120,5121,5123],{},[28,5122,1822],{}," 适合读取以换行结尾的文本协议。",[1818,5125,5126,5127,5130],{},"二进制协议更适合 ",[28,5128,5129],{},"async_read_some()"," 加自己的帧解析器。",[1818,5132,5133],{},"异步写必须注意 buffer 生命周期。",[1818,5135,5136],{},"工程里推荐把串口读写封装成类，并用队列管理发送数据。",[5138,5139,5140],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":26,"searchDepth":218,"depth":218,"links":5142},[5143,5147,5156,5165,5174,5183,5192],{"id":43,"depth":218,"text":44,"children":5144},[5145,5146],{"id":55,"depth":226,"text":56},{"id":107,"depth":226,"text":107},{"id":170,"depth":218,"text":5148,"children":5149},"示例 1：普通 main() 里同步打开串口并发送一行",[5150,5151,5152,5153,5154,5155],{"id":178,"depth":226,"text":178},{"id":199,"depth":226,"text":199},{"id":952,"depth":226,"text":952},{"id":1033,"depth":226,"text":1033},{"id":1056,"depth":226,"text":1056},{"id":1066,"depth":226,"text":1066},{"id":1138,"depth":218,"text":5157,"children":5158},"示例 2：普通 main() 里同步读取一行串口数据",[5159,5160,5161,5162,5163,5164],{"id":1145,"depth":226,"text":178},{"id":1154,"depth":226,"text":199},{"id":1645,"depth":226,"text":952},{"id":1724,"depth":226,"text":1033},{"id":1765,"depth":226,"text":1056},{"id":1777,"depth":226,"text":1066},{"id":1803,"depth":218,"text":5166,"children":5167},"示例 3：普通 main() 里异步读取一行串口数据",[5168,5169,5170,5171,5172,5173],{"id":1810,"depth":226,"text":178},{"id":1843,"depth":226,"text":199},{"id":2521,"depth":226,"text":952},{"id":2597,"depth":226,"text":1033},{"id":2630,"depth":226,"text":1056},{"id":2658,"depth":226,"text":2658},{"id":2751,"depth":218,"text":2752,"children":5175},[5176,5177,5178,5179,5180,5181,5182],{"id":2755,"depth":226,"text":178},{"id":2764,"depth":226,"text":199},{"id":3712,"depth":226,"text":952},{"id":3810,"depth":226,"text":1033},{"id":3837,"depth":226,"text":1056},{"id":3868,"depth":226,"text":3868},{"id":3906,"depth":226,"text":3906},{"id":3983,"depth":218,"text":3984,"children":5184},[5185,5186,5187,5188,5189,5190],{"id":3987,"depth":226,"text":178},{"id":4012,"depth":226,"text":199},{"id":4912,"depth":226,"text":952},{"id":4982,"depth":226,"text":1033},{"id":5001,"depth":226,"text":1056},{"id":5038,"depth":226,"text":5191},"async_write() 说明",{"id":5107,"depth":218,"text":5107},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch19-1-3-chuan-kou-tong-xin","19.1.3",19010300,"2023-10-05","wiki/2023-10-05-cplusplus-jiao-xue","zh-cn:2023-10-05-cplusplus-jiao-xue","/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue","Cplusplus教学","md","wiki/2023-10-05-Cplusplus教学/ch19-1-3-串口通信",false,null,"/wiki/2023-10-05-cplusplus-jiao-xue/ch19-1-3-chuan-kou-tong-xin","zh-CN","zh-cn",{},{"title":5,"description":26},"bJfWw0owazowpiYhIz4uaHGEnw8K3TrLFp234GfDyxA",[5212,5217,5223,5229,5235,5241,5247,5253,5259,5265,5271,5277,5283,5289,5295,5301,5307,5313,5319,5325,5331,5337,5343,5349,5355,5361,5367,5373,5378,5384,5390,5396,5402,5408,5414,5420,5426,5432,5438,5444,5450,5456,5462,5468,5474,5480,5486,5492,5498,5504,5510,5516,5517,5523,5529,5535,5541,5547,5553,5559,5565,5571,5577,5583,5589,5595,5601,5607,5612,5618],{"path":5213,"stem":5214,"title":5215,"date":5196,"chapter":351,"chapterSort":5216,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch1-c-ji-chu-chu-shi","wiki/2023-10-05-Cplusplus教学/ch1-C++基础初识","C++基础初识",1000000,{"path":5218,"stem":5219,"title":5220,"date":5196,"chapter":5221,"chapterSort":5222,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch10-nei-cun-fen-qu-yu-sheng-ming-zhou-qi","wiki/2023-10-05-Cplusplus教学/ch10-内存分区与生命周期","内存分区与生命周期","10",10000000,{"path":5224,"stem":5225,"title":5226,"date":5196,"chapter":5227,"chapterSort":5228,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch11-yin-yong","wiki/2023-10-05-Cplusplus教学/ch11-引用","引用","11",11000000,{"path":5230,"stem":5231,"title":5232,"date":5196,"chapter":5233,"chapterSort":5234,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch12-han-shu-ti-gao-yu-ming-ming-kong-jian","wiki/2023-10-05-Cplusplus教学/ch12-函数提高与命名空间","函数提高与命名空间","12",12000000,{"path":5236,"stem":5237,"title":5238,"date":5196,"chapter":5239,"chapterSort":5240,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch13-1-feng-zhuang","wiki/2023-10-05-Cplusplus教学/ch13-1-封装","封装","13.1",13010000,{"path":5242,"stem":5243,"title":5244,"date":5196,"chapter":5245,"chapterSort":5246,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch13-2-dui-xiang-chu-shi-hua-he-qing-li","wiki/2023-10-05-Cplusplus教学/ch13-2-对象初始化和清理","对象初始化和清理","13.2",13020000,{"path":5248,"stem":5249,"title":5250,"date":5196,"chapter":5251,"chapterSort":5252,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch13-3-dui-xiang-mo-xing-yu-this-zhi-zhen","wiki/2023-10-05-Cplusplus教学/ch13-3-对象模型与this指针","对象模型与this指针","13.3",13030000,{"path":5254,"stem":5255,"title":5256,"date":5196,"chapter":5257,"chapterSort":5258,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch13-4-you-yuan-yu-yun-suan-fu-zhong-zai","wiki/2023-10-05-Cplusplus教学/ch13-4-友元与运算符重载","友元与运算符重载","13.4",13040000,{"path":5260,"stem":5261,"title":5262,"date":5196,"chapter":5263,"chapterSort":5264,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch13-5-ji-cheng","wiki/2023-10-05-Cplusplus教学/ch13-5-继承","继承","13.5",13050000,{"path":5266,"stem":5267,"title":5268,"date":5196,"chapter":5269,"chapterSort":5270,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch13-6-duo-tai","wiki/2023-10-05-Cplusplus教学/ch13-6-多态","多态","13.6",13060000,{"path":5272,"stem":5273,"title":5274,"date":5196,"chapter":5275,"chapterSort":5276,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch13-lei-he-dui-xiang","wiki/2023-10-05-Cplusplus教学/ch13-类和对象","类和对象","13",13000000,{"path":5278,"stem":5279,"title":5280,"date":5196,"chapter":5281,"chapterSort":5282,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch14-wen-jian-cao-zuo","wiki/2023-10-05-Cplusplus教学/ch14-文件操作","文件操作","14",14000000,{"path":5284,"stem":5285,"title":5286,"date":5196,"chapter":5287,"chapterSort":5288,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch15-mu-ban","wiki/2023-10-05-Cplusplus教学/ch15-模板","模板","15",15000000,{"path":5290,"stem":5291,"title":5292,"date":5196,"chapter":5293,"chapterSort":5294,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch16-1-stl-chu-shi","wiki/2023-10-05-Cplusplus教学/ch16-1-STL初识","STL初识","16.1",16010000,{"path":5296,"stem":5297,"title":5298,"date":5196,"chapter":5299,"chapterSort":5300,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch16-2-std-array","wiki/2023-10-05-Cplusplus教学/ch16-2-std-array","std::array","16.2",16020000,{"path":5302,"stem":5303,"title":5304,"date":5196,"chapter":5305,"chapterSort":5306,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch16-3-string-rong-qi","wiki/2023-10-05-Cplusplus教学/ch16-3-string容器","string容器","16.3",16030000,{"path":5308,"stem":5309,"title":5310,"date":5196,"chapter":5311,"chapterSort":5312,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch16-4-vector-yu-deque-rong-qi","wiki/2023-10-05-Cplusplus教学/ch16-4-vector与deque容器","vector与deque容器","16.4",16040000,{"path":5314,"stem":5315,"title":5316,"date":5196,"chapter":5317,"chapterSort":5318,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch16-5-stack-queue-list-rong-qi","wiki/2023-10-05-Cplusplus教学/ch16-5-stack-queue-list容器","stack / queue / list 容器","16.5",16050000,{"path":5320,"stem":5321,"title":5322,"date":5196,"chapter":5323,"chapterSort":5324,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch16-6-set-map-rong-qi","wiki/2023-10-05-Cplusplus教学/ch16-6-set-map容器","set / map 容器","16.6",16060000,{"path":5326,"stem":5327,"title":5328,"date":5196,"chapter":5329,"chapterSort":5330,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch16-7-han-shu-dui-xiang-yu-wei-ci","wiki/2023-10-05-Cplusplus教学/ch16-7-函数对象与谓词","函数对象与谓词","16.7",16070000,{"path":5332,"stem":5333,"title":5334,"date":5196,"chapter":5335,"chapterSort":5336,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch16-8-chang-yong-suan-fa","wiki/2023-10-05-Cplusplus教学/ch16-8-常用算法","常用算法","16.8",16080000,{"path":5338,"stem":5339,"title":5340,"date":5196,"chapter":5341,"chapterSort":5342,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch16-stl-ti-gao-bian-cheng","wiki/2023-10-05-Cplusplus教学/ch16-STL提高编程","STL提高编程","16",16000000,{"path":5344,"stem":5345,"title":5346,"date":5196,"chapter":5347,"chapterSort":5348,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch17-c-lei-xing-zhuan-huan","wiki/2023-10-05-Cplusplus教学/ch17-C++类型转换","C++类型转换","17",17000000,{"path":5350,"stem":5351,"title":5352,"date":5196,"chapter":5353,"chapterSort":5354,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-1-auto","wiki/2023-10-05-Cplusplus教学/ch18-1-auto","auto","18.1",18010000,{"path":5356,"stem":5357,"title":5358,"date":5196,"chapter":5359,"chapterSort":5360,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-10-you-zhi-yin-yong-he-yi-dong-yu-yi","wiki/2023-10-05-Cplusplus教学/ch18-10-右值引用和移动语义","右值引用和移动语义","18.10",18100000,{"path":5362,"stem":5363,"title":5364,"date":5196,"chapter":5365,"chapterSort":5366,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-11-lambda-biao-da-shi","wiki/2023-10-05-Cplusplus教学/ch18-11-Lambda表达式","Lambda 表达式","18.11",18110000,{"path":5368,"stem":5369,"title":5370,"date":5196,"chapter":5371,"chapterSort":5372,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-12-std-function","wiki/2023-10-05-Cplusplus教学/ch18-12-std-function","std::function","18.12",18120000,{"path":5374,"stem":5375,"title":35,"date":5196,"chapter":5376,"chapterSort":5377,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-13-std-bind","wiki/2023-10-05-Cplusplus教学/ch18-13-std-bind","18.13",18130000,{"path":5379,"stem":5380,"title":5381,"date":5196,"chapter":5382,"chapterSort":5383,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-14-std-optional","wiki/2023-10-05-Cplusplus教学/ch18-14-std-optional","std::optional","18.14",18140000,{"path":5385,"stem":5386,"title":5387,"date":5196,"chapter":5388,"chapterSort":5389,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-15-std-variant","wiki/2023-10-05-Cplusplus教学/ch18-15-std-variant","std::variant","18.15",18150000,{"path":5391,"stem":5392,"title":5393,"date":5196,"chapter":5394,"chapterSort":5395,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-16-std-span","wiki/2023-10-05-Cplusplus教学/ch18-16-std-span","std::span","18.16",18160000,{"path":5397,"stem":5398,"title":5399,"date":5196,"chapter":5400,"chapterSort":5401,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-17-std-format-print","wiki/2023-10-05-Cplusplus教学/ch18-17-std-format-print","std::format / std::print","18.17",18170000,{"path":5403,"stem":5404,"title":5405,"date":5196,"chapter":5406,"chapterSort":5407,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-18-std-chrono","wiki/2023-10-05-Cplusplus教学/ch18-18-std-chrono","std::chrono","18.18",18180000,{"path":5409,"stem":5410,"title":5411,"date":5196,"chapter":5412,"chapterSort":5413,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-19-1-std-thread","wiki/2023-10-05-Cplusplus教学/ch18-19-1-std-thread","std::thread 与 join","18.19.1",18190100,{"path":5415,"stem":5416,"title":5417,"date":5196,"chapter":5418,"chapterSort":5419,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-19-2-mutex-lock-guard","wiki/2023-10-05-Cplusplus教学/ch18-19-2-mutex-lock-guard","mutex 与 lock_guard","18.19.2",18190200,{"path":5421,"stem":5422,"title":5423,"date":5196,"chapter":5424,"chapterSort":5425,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-19-3-std-atomic","wiki/2023-10-05-Cplusplus教学/ch18-19-3-std-atomic","std::atomic","18.19.3",18190300,{"path":5427,"stem":5428,"title":5429,"date":5196,"chapter":5430,"chapterSort":5431,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-19-4-condition-variable","wiki/2023-10-05-Cplusplus教学/ch18-19-4-condition-variable","condition_variable","18.19.4",18190400,{"path":5433,"stem":5434,"title":5435,"date":5196,"chapter":5436,"chapterSort":5437,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-19-bing-fa-bian-cheng","wiki/2023-10-05-Cplusplus教学/ch18-19-并发编程","并发编程","18.19",18190000,{"path":5439,"stem":5440,"title":5441,"date":5196,"chapter":5442,"chapterSort":5443,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-2-nullptr","wiki/2023-10-05-Cplusplus教学/ch18-2-nullptr","nullptr","18.2",18020000,{"path":5445,"stem":5446,"title":5447,"date":5196,"chapter":5448,"chapterSort":5449,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-20-std-filesystem","wiki/2023-10-05-Cplusplus教学/ch18-20-std-filesystem","std::filesystem","18.20",18200000,{"path":5451,"stem":5452,"title":5453,"date":5196,"chapter":5454,"chapterSort":5455,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-21-modules-jian-jie","wiki/2023-10-05-Cplusplus教学/ch18-21-modules简介","modules 简介","18.21",18210000,{"path":5457,"stem":5458,"title":5459,"date":5196,"chapter":5460,"chapterSort":5461,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-3-using","wiki/2023-10-05-Cplusplus教学/ch18-3-using","using","18.3",18030000,{"path":5463,"stem":5464,"title":5465,"date":5196,"chapter":5466,"chapterSort":5467,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-4-enum-class","wiki/2023-10-05-Cplusplus教学/ch18-4-enum-class","enum class","18.4",18040000,{"path":5469,"stem":5470,"title":5471,"date":5196,"chapter":5472,"chapterSort":5473,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-5-fan-wei-for-xun-huan","wiki/2023-10-05-Cplusplus教学/ch18-5-范围for循环","范围 for 循环","18.5",18050000,{"path":5475,"stem":5476,"title":5477,"date":5196,"chapter":5478,"chapterSort":5479,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-6-jie-gou-hua-bang-ding","wiki/2023-10-05-Cplusplus教学/ch18-6-结构化绑定","结构化绑定","18.6",18060000,{"path":5481,"stem":5482,"title":5483,"date":5196,"chapter":5484,"chapterSort":5485,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-7-constexpr","wiki/2023-10-05-Cplusplus教学/ch18-7-constexpr","constexpr","18.7",18070000,{"path":5487,"stem":5488,"title":5489,"date":5196,"chapter":5490,"chapterSort":5491,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-8-raii","wiki/2023-10-05-Cplusplus教学/ch18-8-RAII","RAII","18.8",18080000,{"path":5493,"stem":5494,"title":5495,"date":5196,"chapter":5496,"chapterSort":5497,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-9-zhi-neng-zhi-zhen","wiki/2023-10-05-Cplusplus教学/ch18-9-智能指针","智能指针","18.9",18090000,{"path":5499,"stem":5500,"title":5501,"date":5196,"chapter":5502,"chapterSort":5503,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch18-xian-dai-c","wiki/2023-10-05-Cplusplus教学/ch18-现代C++","现代C++","18",18000000,{"path":5505,"stem":5506,"title":5507,"date":5196,"chapter":5508,"chapterSort":5509,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch19-1-1-ding-shi-qi-yu-yi-bu-io","wiki/2023-10-05-Cplusplus教学/ch19-1-1-定时器与异步IO","定时器与异步 IO","19.1.1",19010100,{"path":5511,"stem":5512,"title":5513,"date":5196,"chapter":5514,"chapterSort":5515,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch19-1-2-boost-asio-ji-chu","wiki/2023-10-05-Cplusplus教学/ch19-1-2-Boost.Asio基础","Boost.Asio 基础","19.1.2",19010200,{"path":5193,"stem":5202,"title":5,"date":5196,"chapter":5194,"chapterSort":5195,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},{"path":5518,"stem":5519,"title":5520,"date":5196,"chapter":5521,"chapterSort":5522,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch19-1-4-tcp-tong-xin","wiki/2023-10-05-Cplusplus教学/ch19-1-4-TCP通信","TCP 通信","19.1.4",19010400,{"path":5524,"stem":5525,"title":5526,"date":5196,"chapter":5527,"chapterSort":5528,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch19-1-5-udp-tong-xin","wiki/2023-10-05-Cplusplus教学/ch19-1-5-UDP通信","UDP 通信","19.1.5",19010500,{"path":5530,"stem":5531,"title":5532,"date":5196,"chapter":5533,"chapterSort":5534,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch19-1-6-ji-qi-ren-gong-cheng-xie-fa-yu-ros2-ji-cheng","wiki/2023-10-05-Cplusplus教学/ch19-1-6-机器人工程写法与ROS2集成","机器人工程写法与 ROS2 集成","19.1.6",19010600,{"path":5536,"stem":5537,"title":5538,"date":5196,"chapter":5539,"chapterSort":5540,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch19-1-boost-asio-yi-bu-io-ku","wiki/2023-10-05-Cplusplus教学/ch19-1-Boost.Asio异步IO库","Boost.Asio异步IO库","19.1",19010000,{"path":5542,"stem":5543,"title":5544,"date":5196,"chapter":5545,"chapterSort":5546,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch19-2-eigen-xian-xing-dai-shu-ku","wiki/2023-10-05-Cplusplus教学/ch19-2-Eigen线性代数库","Eigen线性代数库","19.2",19020000,{"path":5548,"stem":5549,"title":5550,"date":5196,"chapter":5551,"chapterSort":5552,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch19-3-opencv-ji-suan-ji-shi-jue-ku","wiki/2023-10-05-Cplusplus教学/ch19-3-OpenCV计算机视觉库","OpenCV计算机视觉库","19.3",19030000,{"path":5554,"stem":5555,"title":5556,"date":5196,"chapter":5557,"chapterSort":5558,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch19-4-pcl-dian-yun-ku","wiki/2023-10-05-Cplusplus教学/ch19-4-PCL点云库","PCL点云库","19.4",19040000,{"path":5560,"stem":5561,"title":5562,"date":5196,"chapter":5563,"chapterSort":5564,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch19-5-sophus-li-qun-li-dai-shu-ku","wiki/2023-10-05-Cplusplus教学/ch19-5-Sophus李群李代数库","Sophus 李群李代数库","19.5",19050000,{"path":5566,"stem":5567,"title":5568,"date":5196,"chapter":5569,"chapterSort":5570,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch19-chang-yong-ku","wiki/2023-10-05-Cplusplus教学/ch19-常用库","常用库学习","19",19000000,{"path":5572,"stem":5573,"title":5574,"date":5196,"chapter":5575,"chapterSort":5576,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch2-shu-ju-lei-xing-yu-shu-ju-cun-fang","wiki/2023-10-05-Cplusplus教学/ch2-数据类型与数据存放","数据类型与数据存放","2",2000000,{"path":5578,"stem":5579,"title":5580,"date":5196,"chapter":5581,"chapterSort":5582,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch3-shu-ru-shu-chu","wiki/2023-10-05-Cplusplus教学/ch3-输入输出","输入输出","3",3000000,{"path":5584,"stem":5585,"title":5586,"date":5196,"chapter":5587,"chapterSort":5588,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch4-yun-suan-fu","wiki/2023-10-05-Cplusplus教学/ch4-运算符","运算符","4",4000000,{"path":5590,"stem":5591,"title":5592,"date":5196,"chapter":5593,"chapterSort":5594,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch5-cheng-xu-liu-cheng-jie-gou","wiki/2023-10-05-Cplusplus教学/ch5-程序流程结构","程序流程结构","5",5000000,{"path":5596,"stem":5597,"title":5598,"date":5196,"chapter":5599,"chapterSort":5600,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch6-shu-zu","wiki/2023-10-05-Cplusplus教学/ch6-数组","数组","6",6000000,{"path":5602,"stem":5603,"title":5604,"date":5196,"chapter":5605,"chapterSort":5606,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch7-han-shu-yu-tou-wen-jian","wiki/2023-10-05-Cplusplus教学/ch7-函数与头文件","函数与头文件","7",7000000,{"path":5608,"stem":5609,"title":5610,"date":5196,"chapter":601,"chapterSort":5611,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch8-zhi-zhen","wiki/2023-10-05-Cplusplus教学/ch8-指针","指针",8000000,{"path":5613,"stem":5614,"title":5615,"date":5196,"chapter":5616,"chapterSort":5617,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":5203},"/zh-cn/wiki/2023-10-05-cplusplus-jiao-xue/ch9-jie-gou-ti-yu-gong-yong-ti","wiki/2023-10-05-Cplusplus教学/ch9-结构体与共用体","结构体与共用体","9",9000000,{"path":5199,"stem":5619,"title":5620,"date":5196,"chapter":5204,"chapterSort":5621,"docKey":5198,"docRoot":5199,"docTitle":5200,"isWikiDoc":245,"isWikiIndex":245},"wiki/2023-10-05-Cplusplus教学/index","C/C++教程",0,{"variants":5623},[5624,5627,5630,5633,5636],{"path":5625,"localeSlug":5626,"i18nKey":5202},"/en-us/wiki/2023-10-05-cplusplus-jiao-xue/ch19-1-3-chuan-kou-tong-xin","en-us",{"path":5628,"localeSlug":5629,"i18nKey":5202},"/zh-hant/wiki/2023-10-05-cplusplus-jiao-xue/ch19-1-3-chuan-kou-tong-xin","zh-hant",{"path":5631,"localeSlug":5632,"i18nKey":5202},"/zh-hk/wiki/2023-10-05-cplusplus-jiao-xue/ch19-1-3-chuan-kou-tong-xin","zh-hk",{"path":5634,"localeSlug":5635,"i18nKey":5202},"/zh-tw/wiki/2023-10-05-cplusplus-jiao-xue/ch19-1-3-chuan-kou-tong-xin","zh-tw",{"path":5193,"localeSlug":5207,"i18nKey":5202},[5625,5205,5628,5205,5631,5205,5634,5205,5193,5205],1780663039668]