RPC between C++ and Java

Karthik Nadig

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.


4 Responses to “RPC between C++ and Java”

Leave a Reply