要求:
- Java调用程序调用在其自己的进程中运行的C计算器程序
- Java发送操作
- C程序返回结果
- 尽可能避免JNI/JNA
最简单的方法可能是从Java调用C程序并通过标准I/O进行通信.C程序可以通过循环中的stdin
获得操作,进行计算,并通过stdout
返回结果.
在Java中,实现这一点的核心机制是Process
类.Oracle's documentation个州:
Process提供对ProcessBuilder启动的本机进程的控制.开始
为了避免死锁,我们交替地写一行要执行的操作,并读回一行结果.
使用stdin
和stdout
的优点当然也是手动ad hocs可测试性,因为您可以在命令行上简单地调用C程序.顺便说一句,这种方法在Linux和macOS下也同样适用.
为了获得尽可能简单的测试用例,这里有一个C程序,它可以获得带有两个参数的加减运算符,计算结果并返回结果.当然,整个过程不包括CUDA和最小的错误处理,可能不满足详细的要求,但这可能是朝着正确方向的开始.
Java演示程序最终调用此C程序,并向C程序发送加减运算,并相应地输出返回的结果.然后,q
命令终止C程序.
Java
package com.software7.test;
import java.io.*;
public class Caller {
public static void main(String[] args) {
Caller caller = new Caller();
caller.runCCalculator();
}
private void runCCalculator() {
try {
String[] command = { "C:\\Users\\stephan\\source\\repos\\CCalculator\\x64\\Debug\\CCalculator.exe" };
ProcessBuilder processBuilder = new ProcessBuilder(command);
Process process = processBuilder.start();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String[] ops = {"+ 1.1 2.2", "- 1024.123 512.123"};
for (String op : ops) {
bw.write(op);
bw.write("\n");
bw.flush();
String result = br.readLine();
if (result != null) {
System.out.println(op + " = " + result);
}
}
bw.write("q\n");
bw.flush();
bw.close();
br.close();
System.out.println("Process exited with " + process.waitFor());
} catch (IOException | InterruptedException exp) {
exp.printStackTrace();
}
}
}
C
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static void error_exit(const char *msg);
static char readOp(const char *token);
static double readArg(const char *token);
int main(void) {
char buf[128];
char *ptr;
while ((ptr = fgets(buf, sizeof(buf), stdin)) != NULL) {
buf[strcspn(buf, "\n")] = 0;
if (strcmp(ptr, "q") == 0) {
break;
}
char *token = strtok(ptr, " ");
char op = readOp(token);
token = strtok(NULL, " ");
double val1 = readArg(token);
token = strtok(NULL, " ");
double val2 = readArg(token);
switch (op) {
case '+':
printf("%lf\n", val1 + val2);
fflush(stdout);
break;
case '-':
printf("%lf\n", val1 - val2);
fflush(stdout);
break;
default:
error_exit("unknown operator");
}
}
return 0;
}
static char readOp(const char *token) {
if (token != NULL) {
return *token;
} else {
error_exit("no operator");
}
}
static double readArg(const char *token) {
double res;
if (token != NULL) {
char *end_ptr;
res = strtod(token, &end_ptr);
if (token == end_ptr || *end_ptr != '\0') {
error_exit("invalid float operand");
}
} else {
error_exit("invalid operand");
}
return res;
}
static void error_exit(const char *msg) {
fprintf(stderr, "%s\n", msg);
exit(1);
}
Result
+ 1.1 2.2 = 3.300000
- 1024.123 512.123 = 512.000000