RPC between C++ and Java
Chinese version (By Haosha Wang) : Link
A friend from my university posted a question about calling a method in Java from C++. Some of the recommendations were to use JNI. I, however, prefer RPC. This is how you do it.
Preparation
I use XML-RPC as the wire protocol in my example. For Java I use apache XML-RPC implementation and for C++ I use XML-RPC for Windows. My example will work on Windows. However, this is not that hard to port to other OS.
The Java Server
Let’s start with the server part. Here, the server is implemented using Java. Before we get to server code, we need to think through the method we want to execute. You can add more methods as necessary.
1: public class MathComputation {
2: public static double PI = 3.14159265358979323846;
3: public static final int DEFAULT = 0;
4: public static final int INVERSE = 1;
5:
6: public double ComputePi(int valType)
7: {
8: double result = 0;
9:
10: switch(valType)
11: {
12: case DEFAULT:
13: result = PI;
14: break;
15: case INVERSE:
16: result = 1.0/PI;
17: break;
18: }
19:
20: return result;
21: }
22: }
Now, for the server part:
1: import org.apache.xmlrpc.server.*;
2: import org.apache.xmlrpc.webserver.*;
3:
4: public class RPCServer {
5: public static void main(String[] args) {
6: try{
7: // TODO: put server code here
8: }
9: catch(Exception ex)
10: {
11: System.out.println(ex.getMessage());
12: ex.printStackTrace(System.out);
13: }
14: }
15: }
First, set up a webserver (a XML-RPC webserver) and the end-point for it (line 3). In this example, it will be localhost and port 8080. Second, get the instance of the XML-RPC server from the XML-RPC webserver (line 6). Use the PropertyHandlerMapping class to expose the classes and methods you would like to use (line 9-10). Then, we use our instance of the PropertyHandlerMapping class to set up the XML-RPC server (line 14). Third, you will need to set the server settings. In this case, I enabled extensions and usually the content length has to be there in the header for the RPC call (line 17-20). Last step, start the server (line 23).
1: // Create a web server end-point
2: // This is local host port:8080
3: WebServer webServer = new WebServer(8080);
4:
5: // Get the instance of the RPC server
6: XmlRpcServer xmlRpcServer = webServer.getXmlRpcServer();
7:
8: // All the classes you will be using over RPC here
9: PropertyHandlerMapping phm = new PropertyHandlerMapping();
10: phm.addHandler("MathComputation", MathComputation.class);
11:
12: // This sets up XML-RPC server to have access to all
13: // the needed methods
14: xmlRpcServer.setHandlerMapping(phm);
15:
16: // These are server properties, enable them as you need.
17: XmlRpcServerConfigImpl serverConfig =
18: (XmlRpcServerConfigImpl) xmlRpcServer.getConfig();
19: serverConfig.setEnabledForExtensions(true);
20: serverConfig.setContentLengthOptional(false);
21:
22: // Start the server and you are ready
23: webServer.start();
That is all for the Java part. You can find the code files here, you also need apache XML-RPC for this to work.
The CPP Client
The client part will be in CPP. Create a project in your favorite IDE and add the following lib: wininet.lib, for windows. The lib contains APIs to interact with FTP and HTTP protocols while using Internet resources. I used XML-RPC for Windows from sourceforge (download link here). Add the following files to your CPP Client project: timxmlrpc.h, timxmlrpc.cpp.
The following code is all you need to talk to the Java XML-RPC server. I repurposed this sample from the sample that is in the zip file for XML-RPC for Windows. First, create an array of arguments using the XmlRpcValue (line 10-13). In this case, we need only one argument. See the examples in the zip file (XML-RPC for Windows) for other types of arguments. Second, set up a connection to the Java server you created (line 16), remember to run it before you run the client. Make a call to Java server, if the call succeeds then the return values will be available in XML-RPC format. Last step, get it into a form that is useful to you.
1: #include "stdafx.h"
2: #include <iostream>
3: #include "TimXmlRpc.h"
4:
5: #define MATH_DEFAULT 0
6: #define MATH_INVERSE 1
7:
8: void main(int argc, char* argv[])
9: {
10: XmlRpcValue args, result;
11:
12: // Pass arguments here
13: args[0] = MATH_DEFAULT;
14:
15: // Setup a connection with the XML-RPC server endpoint
16: XmlRpcClient Connection("http://localhost:8080");
17: Connection.setIgnoreCertificateAuthority();
18:
19: // Make the call to the XML-RPC Java webserver.
20: if (! Connection.execute(
21: "MathComputation.ComputePi",
22: args,
23: result))
24: {
25: // Something went wrong
26: std::cout << Connection.getError();
27: return;
28: }
29:
30: // Retrieve the return value from the call
31: // Check if the return type is the same as expected
32: if (result.getType() != XmlRpcValue::TypeDouble)
33: {
34: std::cout << "Expecting Double.";
35: return;
36: }
37:
38: // Get the result from the call in the form you want
39: double pi = (double)result;
40:
41: std::cout.precision(15);
42: std::cout << pi;
43: }
C++ code files can be found here, don’t forget to download and include timxmlrpc.h, timxmlrpc.cpp. Also, remember to add wininet.lib to your CPP Client project. Let me know in the comments if you have any issue.
May 27th, 2013 at 23:56
[…] 英文版: 链接 […]
May 28th, 2013 at 11:11
[…] For his original English version: Link / 英文原版:链接 […]
April 14th, 2014 at 02:07
how can i using java to access rpc methods implemented in C++?
April 14th, 2014 at 02:11
and the rpc methods are implemented in C++ in Linux System