define your classes in jni/example.h
Code: Select all
/* File : example.h */
class Shape {
public:
Shape() {
nshapes++;
}
virtual ~Shape() {
nshapes--;
};
double x, y;
void move(double dx, double dy);
virtual double area(void) = 0;
virtual double perimeter(void) = 0;
static int nshapes;
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) { };
virtual double area(void);
virtual double perimeter(void);
};
class Square : public Shape {
private:
double width;
public:
Square(double w) : width(w) { };
virtual double area(void);
virtual double perimeter(void);
};
and the implementation in jni/example.cpp
Code: Select all
/* File : example.cpp */
#include "example.h"
#define M_PI 3.14159265358979323846
/* Move the shape to a new location */
void Shape::move(double dx, double dy) {
x += dx;
y += dy;
}
int Shape::nshapes = 0;
double Circle::area(void) {
return M_PI*radius*radius;
}
double Circle::perimeter(void) {
return 2*M_PI*radius;
}
double Square::area(void) {
return width*width;
}
double Square::perimeter(void) {
return 4*width;
}
Create a SWIG interface file for this C++ code in jni/example.i:
Code: Select all
/* File : example.i */
%module example
%{
#include "example.h"
%}
/* Let's just grab the original header file here */
%include "example.h"
NOTE: the classes are not defined in the SWIG file but only the header file is exposed. The module is called example
Invoke SWIG as follows, note that the -c++ option is required for C++ code:
Code: Select all
$ swig -c++ -java -package org.swig.classexample -outdir src/org/swig/classexample -o jni/example_wrap.cpp jni/example.i
SWIG generates the following files:
Code: Select all
src/org/swig/classexample/Square.java
src/org/swig/classexample/exampleJNI.java
src/org/swig/classexample/example.java
src/org/swig/classexample/Circle.java
src/org/swig/classexample/Shape.java
jni/example_wrap.cpp
Create the makefile to build the C++ in jni/Android.mk:
Code: Select all
# File: Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := example
LOCAL_SRC_FILES := example_wrap.cpp example.cpp
LOCAL_CFLAGS := -frtti
include $(BUILD_SHARED_LIBRARY)
build the code:
$ ndk-build
Compile++ thumb : example <= example_wrap.cpp
Compile++ thumb : example <= example.cpp
StaticLibrary : libstdc++.a
SharedLibrary : libexample.so
Install : libexample.so => libs/armeabi/libexample.so
Now, let's use those classes from the java:
Code: Select all
/** Calls into C/C++ code */
public void nativeCall()
{
// ----- Object creation -----
Circle c = new Circle(10);
outputText.append( " Created circle " + c + "\n");
Square s = new Square(10);
outputText.append( " Created square " + s + "\n");
// ----- Access a static member -----
outputText.append( "\nA total of " + Shape.getNshapes() + " shapes were created\n" );
// ----- Member data access -----
// Notice how we can do this using functions specific to the 'Circle' class.
c.setX(20);
c.setY(30);
// Now use the same functions in the base class
Shape shape = s;
shape.setX(-10);
shape.setY(5);
// ----- Call some methods -----
Shape[] shapes = {c,s};
for (int i=0; i<shapes.length; i++)
{
outputText.append( " " + shapes[i].toString() + "\n" );
outputText.append( " area = " + shapes[i].area() + "\n" );
outputText.append( " perimeter = " + shapes[i].perimeter() + "\n" );
}
// Notice how the area() and perimeter() functions really
// invoke the appropriate virtual method on each object.
// ----- Delete everything -----
// Note: this invokes the virtual destructor. You could leave this to the garbage collector
c.delete();
s.delete();
}
/** static constructor */
static {
System.loadLibrary("example");
}
NB: if you are using STL in C++:
Should the C++ Standard Template Library (STL) be required, an Application.mk file needs to be created in the same directory as the Android.mk directory containing information about the STL to use.
See the NDK documentation in the $NDKROOT/docs folder especially CPLUSPLUS-SUPPORT.html.
Below is an example of the Application.mk file to make the STLport static library available for use:
# File: Application.mk
APP_STL := gnustl_static