昨天在实现一个Java程序启动执行C++程序中,遇到了一些问题,先准备把它记录下来(利人利己)
准备实现的测试功能是这样的:在一个java程序中启动一个C++可执行程序,然后java程序和C++程序相互通信(java端发送消息给C++程序处理,C++处理完成后将返回一个结果消息给java程序。不断往返循环直至输入exit指令结束)。
首先,在一个java程序中启动一个C++可执行程序 使用的是java的Runtime.getRuntime().exec(),Process类exec()官方说明 http://docs.oracle.com/javase/6/docs/api/java/lang/Process.html
【另外,还有一种java的JNI (Java Native Interface)框架可以实现java调用其它编程语言的方法】
*说明*:
使用exec()方式,C++程序的所有标准 io(即 stdin、stdout和
stderr)操作都将通过三个流(getOutputStream()、getInputStream()和
getErrorStream()) 重定向到父进程。
因此,使用上述重定向特性就可以通过标准输入输出实现Java与C++程序间的简单通信,在处理通信I/O时,使用了BufferedReader和BufferedWriter作为通信输入输出的缓冲,方便对消息处理。
关于readLine(),此处有篇博文点击打开链接 http://blog.csdn.net/swingline/article/details/5357581
*注意*:
1. 由于C++端是按行读取消息的,所以在Java端发送消息时要注意每个消息的结尾都必须加上换行符。这就是为何我在writeToCpp.write(wstr+"\n"); 中要+"\n"的原因。(就是因为这个换行符没加导致我调bug费了好长时间,之前一直找不出什么原因导致java端在console中输入消息发送后java程序就跑飞了。。后来发现在eclipse的console中输入字符串回车后该字符串末尾是不带换行符的。。。)
2. 下面的java代码中开辟了一个线程来处理从C++端传送来的消息打印。非常好用!
3. 【引用自点击打开链接】
- 误以为readLine()是读取到没有数据时就返回null(因为其它read方法当读到没有数据时返回-1),而实际上readLine()是一个阻塞函数,当没有数据读取时,就一直会阻塞在那,而不是返回null;因为readLine()阻塞后,System.out.println(message)这句根本就不会执行到,所以在接收端就不会有东西输出。要想执行到System.out.println(message),一个办法是发送完数据后就关掉流,这样readLine()结束阻塞状态,而能够得到正确的结果,但显然不能传一行就关一次数据流;另外一个办法是把System.out.println(message)放到while循环体内就可以。
另外有个问题没解决:
针对Java启动C++程序场景,如何配置使用eclipse和visual studio (2013)使得我能够从eclipse中debug Java程序跟踪到C++程序后能在Visual studio中继续能debug呢?
我查了下,好像可以通过Visual studio的attach to process功能能够实现联调(在VS中依次打开Debug -> Attach to process. 然后找到启动的java进程选中确定【我选的是javaw.exe】),但是我尝试了好久没有成功。(一开始提示找不到PDB文件,我就去vs的TOOLS -> Options -> Debugging -> Symbols勾选了“Microsoft Symbol Servers” ,部分PDB文件就可以加载了,但还有部分PDB文件加载不上。。。打的断点也是显示黄色圆圈带感叹号
【提示信息见下文】)
还请有经验的大侠能帮忙提供下eclipse与VS联调的解决方案,谢谢!!
下面就是实现了双边通信的java和C++源代码
Java端代码片段:
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.Scanner; public class JavaCallCpp { static BufferedWriter writeToCpp; static BufferedReader readFromCpp; public static void main(String[] args) throws IOException { try { Process execute = Runtime.getRuntime().exec("D:/WorkSpace/vs/stringstream/Debug/stringstream"); //int exitVal = execute.waitFor(); writeToCpp = new BufferedWriter(new OutputStreamWriter(execute.getOutputStream())); readFromCpp = new BufferedReader(new InputStreamReader(execute.getInputStream())); MyThread myThread=new MyThread(readFromCpp); myThread.start(); /*Write to C++*/ writeToCpp.write("have entered the scentence\n"); writeToCpp.write("aaaaa\n"); writeToCpp.flush(); //writeToCpp.write("quit\n"); //writeToCpp.flush(); /*Read from C++*/ writeToCpp.write("abcd\n"); writeToCpp.flush(); Scanner writer = new Scanner(System.in); // while(true){ String wstr = null; while(true){ wstr=writer.next(); if(wstr.equals("exit")){ writer.close(); break; } System.out.println(wstr); writeToCpp.write(wstr+"\n"); writeToCpp.flush(); } writeToCpp.flush(); System.out.println("out of while."); /*while((readLine = readFromCpp.readLine()) != null){ System.out.println(readLine); }*/ // } //writerString.close(); execute.destroyForcibly();//强制终止 execute.getInputStream().close(); readFromCpp.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
class MyThread extends Thread{ private BufferedReader bfr; public MyThread(BufferedReader bfr){ this.bfr=bfr; } @Override public void run() { // TODO Auto-generated method stub super.run(); String readLine = null; Boolean _b=true; try { while(_b){ readLine=bfr.readLine(); if(readLine==null) { _b=false; }else{ System.out.println(readLine); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
C++端程序片段:
void fun1(){ string cmd; string line, word; cout << "enter a scentence, and exit with typing \"quit\""<<endl; while (getline(cin, line)&& line!="quit") { stringstream stream(line); cout << stream.str() << endl; while (stream >> word){ cout << word << endl; } } while (true){ cout << "please input a command, and exit with typing \"exit\": "<<endl; getline(std::cin, cmd); if (0==strcmp(cmd.c_str(),"exit")){ //strcmp返回str1-str2的值 cout << "cmd is exit, exit 0 \n"; exit (0); } else if (strcmp(cmd.c_str(), "continue") !=0){ cout << "cmd is not \"continue\" to break\n"; continue; } else{ cout << "cmd is continue, break while(true) \n"; break; } } cout << "OK, pass over while(true) \n"; }
/*以下是针对debug问题的(可忽略)*/
eclipse与visual studio联调debug的提示信息:
'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\bin\javaw.exe'. Cannot find or open the PDB file. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\ntdll.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\kernel32.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\KernelBase.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\advapi32.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\msvcrt.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\sechost.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\rpcrt4.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\user32.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\gdi32.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.10586.0_none_8c15ae12515e1c22\comctl32.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\combase.dll'. Cannot find or open the PDB file. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\bcryptprimitives.dll'. Cannot find or open the PDB file. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\imm32.dll'. Cannot find or open the PDB file. 'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\jre\bin\msvcr100.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\jre\bin\server\jvm.dll'. Cannot find or open the PDB file. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\psapi.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\wsock32.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\ws2_32.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\version.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\winmm.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\winmmbase.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\cfgmgr32.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\jre\bin\verify.dll'. Cannot find or open the PDB file. 'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\jre\bin\java.dll'. Cannot find or open the PDB file. 'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\jre\bin\jdwp.dll'. Cannot find or open the PDB file. 'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\jre\bin\npt.dll'. Cannot find or open the PDB file. 'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\jre\bin\zip.dll'. Cannot find or open the PDB file. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\shell32.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\windows.storage.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\shlwapi.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\kernel.appcore.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\SHCore.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\powrprof.dll'. Cannot find or open the PDB file. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\profapi.dll'. Cannot find or open the PDB file. 'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\jre\bin\dt_socket.dll'. Cannot find or open the PDB file. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\NapiNSP.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\pnrpnsp.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\nlaapi.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\mswsock.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\dnsapi.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\nsi.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\winrnr.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\wshbth.dll'. Symbols loaded. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\FWPUCLNT.DLL'. Cannot find or open the PDB file. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\bcrypt.dll'. Cannot find or open the PDB file. 'javaw.exe' (Win32): Loaded 'C:\Windows\System32\rasadhlp.dll'. Cannot find or open the PDB file.