Java调用C++ swig

Swig介绍

swig github SWIG (Simplified Wrapper and Interface Generator)
可以用来在多个编程语言之间进行跨语言封装接口,实现不同编程语言之间的调用。
本文是使用Swig生成Java接口调用C++编译的Linux 平台的so
首先需要安装Swig Swig安装方法

类型映射

如何将C++中的类型映射到Java常用的类:swig typemaps

std::string

比如常用c++的std::string和java的String可以在.i文件中加%include “std_string.i”

Java Array

使用Java Array对应C的指针和长度,例如 java的int[] 转成c++的int * 和长度。
在example.i里面加如下定义:

%include "arrays_java.i"
%apply short[] {short *};

详细列表如下图:

Java 调用C++ SO

主要步骤如下:

  1. 开发C++相关代码如下面example.h和example.cpp加上下面4步骤中提到的自动生成的C++ JNI文件
  2. 选择接口文件比如:example.h
  3. 编写Swig要求的接口描述文件,下面的example.i文件内容
  4. 使用Swig命令自动生成Java接口类文件和C++的JNI的example_warp.cpp(需要加到SO工程编译)。Java工程需要指定API的包名swig -c++ -java -package com.example.ai -outdir java/ example.i
  5. 将步骤4中生成的Java类等放到Java工程src目录,将第一步的SO库放到Java能找到路径的动态库目录里面。按下面的Java示例即可调用SO函数。
    example.h 实例:
/* File : example.h */

class Shape {
public:
  Shape() {
    nshapes++;
  }
  virtual ~Shape() {
    nshapes--;
  }
  double  x, y;
  void    move(double dx, double dy);
  void copyIntArray(int *pArray, int nArraySize);
  virtual double area() = 0;
  virtual double perimeter() = 0;
  static  int nshapes;
};

class Circle : public Shape {
private:
  double radius;
public:
  Circle(double r) : radius(r) { }
  virtual double area();
  virtual double perimeter();
};

class Square : public Shape {
private:
  double width;
public:
  Square(double w) : width(w) { }
  virtual double area();
  virtual double perimeter();
};

example.cxx

/* File : example.cxx */

#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() {
  return M_PI*radius*radius;
}

double Circle::perimeter() {
  return 2*M_PI*radius;
}

double Square::area() {
  return width*width;
}
void copyIntArray(int *pArray, int nArraySize) {
	for(int i=0; i<nArraySize; ++i){
		printf("%d ", pArray[i];);
	}
	printf("\n");
}
double Square::perimeter() {
  return 4*width;
}

example.i

或者使用效率更高的

/* File : example.i */
%module example
%include "carrays.i"
%include "stdint.i"
%{
#include "example.h"
%}
// 将short *的不定长数组自动生成使用函数
%array_functions(int, shortArray);
/*%array_functions(int, shortArray); 会生成如下函数:
int *new_intArray(int nelements);
void delete_intArray(int *x);
int intArray_getitem(int *x, int index);
void intArray_setitem(int *x, int index, int value);
*/
/* Let's just grab the original header file here */
%include "example.h"

Java 示例代码

// This example illustrates how C++ classes can be used from Java using SWIG.
// The Java class gets mapped onto the C++ class and behaves as if it is a Java class.

public class runme {
  static {
    try {
        System.loadLibrary("example");
    } catch (UnsatisfiedLinkError e) {
      System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
      System.exit(1);
    }
  }

  public static void main(String argv[]) 
  {
    // ----- Object creation -----
    
    System.out.println( "Creating some objects:" );
    Circle c = new Circle(10);
    System.out.println( "    Created circle " + c );
    Square s = new Square(10);
    System.out.println( "    Created square " + s );
    
    // ----- Access a static member -----
    
    System.out.println( "\nA total of " + Shape.getNshapes() + " shapes were created" );
    
    // ----- 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);
    
    System.out.println( "\nHere is their current position:" );
    System.out.println( "    Circle = (" + c.getX() + " " + c.getY() + ")" );
    System.out.println( "    Square = (" + s.getX() + " " + s.getY() + ")" );
    
    // ----- Call some methods -----
    
    System.out.println( "\nHere are some properties of the shapes:" );
    Shape[] shapes = {c,s};
    for (int i=0; i<shapes.length; i++)
    {
          System.out.println( "   " + shapes[i].toString() );
          System.out.println( "        area      = " + shapes[i].area() );
          System.out.println( "        perimeter = " + shapes[i].perimeter() );
    }
    
    // Notice how the area() and perimeter() functions really
    // invoke the appropriate virtual method on each object.
    
    // ----- Delete everything -----
    
    System.out.println( "\nGuess I'll clean up now" );
    
    // Note: this invokes the virtual destructor
    // You could leave this to the garbage collector
    c.delete();
    s.delete();
    
    System.out.println( Shape.getNshapes() + " shapes remain" );
    System.out.println( "Goodbye" );
  }
}

swig 官网文档
Link Java and C ++ code with SWIG

你可能感兴趣的:(Linux,Android,java,c++)