[Java] Glue Java and C++ Together Using SWIG (OpenCV Example)

Call native applications in Java

It happens that we want to use C++ code in Java application when we want to reuse our old C++ code, or when we would like to take advantages of the C++ executing speed, or when we don’t have the source code but only C++ libraries.

As we know, Java Native Interface (JNI) is a framework that enables Java code run on Java Virtual Machine (JVM) to call or to be called by native applications (e.g. C++ libraries). JNI Wiki

SWIG provides a relatively convenient way to wrap C++ libraries to be called by Java. It provides relatively easy method for class constructors and type mapping.

How to use SWIG (Ubuntu)

1. Download and install SWIG: Link

2. Write a interface file (*.h) which defines type mapping and included headers.

For SWIG, the only important C++ file is header files (*.h).  When we use SWIG to generate Java wrappers for C++ libraries, we only tell SWIG where to find the C++ header file instead of all the C++ source code.


%module example
%include "typemaps.i"
// for std::string type-maps
%include "std_string.i"
%typemap(jstype) cv::Mat "org.opencv.core.Mat"
%typemap(javain) cv::Mat "$javainput.getNativeObjAddr()"
%typemap(jtype) cv::Mat "long"
%typemap(jni) cv::Mat "jlong"
%typemap(in) cv::Mat {
    $1 = **(cv::Mat **)&$input;
}
%typemap(javaout) cv::Mat {
return new org.opencv.core.Mat($jnicall);
}
%{
    // include header to wrap
    #include "example.h"
    // include other dependencies headers
    #include <opencv2/opencv.hpp>
%}
// include header to wrap (relative path)
%include "../include/example.h" 

3. Use SWIG command to generate wrapper .cxx file and .java files.


swig -java -c++ -package com.your.domain.package.name example.h

4. Build generated .cxx files into c++ libraries.

5. Copy generated .java files to your package directory.

6. Load the C++ library


// direct load method by absolute path

System.load("absolute/path/to/library");

// search in library path with library name

System.loadLibrary("libraryname");

7. Use the library in Java as in C++ Done.

Observations

The most complicated part which should be paid good attention is the type mapping part. Some C++ native types (such as int, float and double) could be mapped by SWIG automatically. The other types cannot be mapped automatically will generate SWIGTYPE_p_cv__*.java file which indicates that there are errors when SWIG trying to type mapping such C++ types.

For C++ classes, private members are fine and will not be wrapped into Java. Therefore, their types need not to be handled by type mapping in SWIG. (which is excellent!)

Note that Java doesn’t support “pass by reference” (int&, double&) which is supported by C++. Java will pass all the parameters by creating new entities. Therefore when dealing with C++ code using “pass by reference”, we may want to write it into classes and store the variable in class public members to access their value.

If the C++ code is written nicely objective oriented (e.g. include dependencies headers only in .cpp file, store accessible variables as class public members, hide unuseful variables and functions as private members), the SWIG wrapping process will be much easier.

Reference

How to glue C++ and Java together

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a free website or blog at WordPress.com.

Up ↑

%d bloggers like this: