浏览 4407 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-06-26
最后修改:2010-06-27
为了避免与port进程的通信受一些printf调试信息的影响,通常都要关闭或者替换标准输入输出。
#include "stdafx.h" #include <stdio.h> #include <iostream> #include <io.h> #include <fcntl.h> #include <windows.h> int main(int argc, char* argv[]) { //复制stdio fd,之后我们将使用复制的句柄与Erlang通信 FILE* f0 = fdopen(dup(0),"rb"); FILE* f1 = fdopen(dup(1),"wb"); //Windows下默认为Text模式,按需要设置为BINARY模式, //否则\n将会被替换为\r\n,这通常不是我们想要的 _setmode (_fileno(f0), _O_BINARY); _setmode (_fileno(f1), _O_BINARY); //用一个临时文件替换stdio,并关闭之 FILE* ftmp = tmpfile(); dup2(fileno(ftmp), 0); dup2(fileno(ftmp), 1); fclose(stdin); fclose(stdout); fclose(ftmp); //测试一些输出 fwrite("hello",1,5,f1); fputc(' ',f1); fflush(f1); printf("world"); fflush(stdout); std::cout << "!!!!!\n"; std::cout.flush(); Sleep(5000); return 0; }
测试用erlang代码:
-module(test). -compile(export_all). start() -> P = open_port({spawn, "./Debug/teststdio.exe"},[binary]), loop(P). loop(P) -> receive {P, {data, Data}} -> io:format("~p~n",[Data]), loop(P) after 3000 -> timeout end.
测试结果:
1、替换stdio后: Eshell V5.7.5 (abort with ^G) 1> c(test.erl). {ok,test} 2> test:start(). <<"hello ">> timeout 3>
2、如果没有替换stdio,将会收到 test:start(). <<"hello ">> <<"world">> <<"!!!!!\r\n">> timeout
我们调用第三方库时很难确认是否会有stdio输出,这种方式很好的避免了printf信息对port通信的影响
注意没有替换stdio部分的输出,stdin和stdout没有指定BINARY模式,\n被替换成\r\n了, 再看看前面dup2部分的调用,虽然指定了"rb"和"wb",但这样是无效的,必须手动调用setmode进行设置才会有效
最后说说windows下使用异步stdio的注意点,需要2个设置: 1、在open_port中指定overlapped_io参数 2、用_get_osfhandle函数得到替换后的io的HANDLE,以供ReadFile和WriteFile操作:
HANDLE hin = (HANDLE)_get_osfhandle(_fileno(f0)); HANDLE hout= (HANDLE)_get_osfhandle(_fileno(f1));
在C程序里使用异步io虽然麻烦,但有时候却是必须的。比如windows系统下通过port访问串行口时,如果不使用overlapped模式,读取串口与读取stdio是不能同时进行的。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-06-28
感谢,感谢。
最近正因为“\n将会被替换为\r\n” 测试了很多方法。 _setmode (_fileno(f1), _O_BINARY); 后,传输没问题,特别是二进制文件。 |
|
返回顶楼 | |
发表时间:2010-08-24
星爷威武!
|
|
返回顶楼 | |