Introdução e uso do SWIG

Site oficial: https://www.swig.org/ github: https://github.com/swig

SWIG é uma ferramenta de desenvolvimento de software que faz interface entre programas escritos em C e C++ com várias linguagens de programação de alto nível.

SWIG funciona com diferentes tipos de linguagens de destino, incluindo linguagens de script comuns, como Javascript, Perl, PHP, Python, Tcl e Ruby. A lista de linguagens suportadas também inclui linguagens sem script, como C#, D, a linguagem Go, Java incluindo Android, Lua, OCaml, Octave, Scilab e R. Várias implementações de esquema interpretadas e compiladas também são suportadas (Guile, MzScheme/Racket).SWIG é mais comumente usado para criar ambientes de programação interpretados ou compilados de alto nível, interfaces de usuário e como uma ferramenta para teste e prototipagem de software C/C++. SWIG é normalmente usado para analisar a interface C/C++ e gerar o "código cola" necessário para que a linguagem de destino acima chame o código C/C++. SWIG também pode exportar sua árvore de análise como XML. SWIG é um software livre e o código gerado pelo SWIG é compatível com projetos comerciais e não comerciais.

Baixar e instalar:

https://www.swig.org/download.html

./configure --prefix=/usr \
            --without-maximum-compile-warnings &&
make
make install 

1.SWIG para java:

Site oficial: SWIG e Java

As extensões Java do SWIG facilitam muito o acesso ao código C/C++ existente do Java porque o SWIG escreve o código Java Native Interface (JNI) para você. É diferente de usar a ferramenta "javah" porque SWIG agrupará o código C/C++ existente, enquanto javah pega declarações de função Java "nativas" e cria protótipos de função C/C++. SWIG agrupa código C/C++ com classes de proxy Java, o que é útil se você deseja acessar muitos códigos C/C++ de Java. Usar SWIG pode ser um exagero se você precisar apenas de uma ou duas funções JNI. SWIG permite que programas Java chamem facilmente código C/C++ de Java. Historicamente, o SWIG não conseguiu gerar nenhum código para chamar código Java de C++. No entanto, SWIG agora suporta polimorfismo completo entre linguagens e gera código para chamar de C++ para Java ao agrupar um método virtual C++.

LightGBM4j: um wrapper java para LightGBM, usando SWIG.

https://github.com/metarank/lightgbm4j

1) A diferença entre SWIG e JNA:

2) O que o SWIG para java pode fazer?

SWIG serve para gerar código intermediário para outras linguagens de programação que podem chamar bibliotecas escritas em C e C++. Por exemplo, se você sabe que Java pode chamar C e C++ por meio de JNI, então SWIG está "fazendo coisas JNI".

Aqui está uma explicação de "fazer coisas JNI": quando estamos desenvolvendo Java, em alguns casos precisamos chamar uma biblioteca desenvolvida em C. Mas não há como o código Java chamar diretamente a biblioteca desenvolvida por C. Ele precisa ser desenvolvido em aproximadamente duas etapas:

Na primeira etapa, você precisa escrever um código de camada Java, carregar a biblioteca so e declarar um método nativo:

//MyFunJNI.java文件,包名为: com.my.fun
public class MyFunJNI {
  static {
      System.loadLibrary("myfun");
  }
  public final static native int doFun();
}

Na segunda etapa, você precisa escrever um código da camada C correspondente ao método doFun na primeira etapa MyFunJNI e chamar a função int c_fun() na biblioteca C que deseja usar:

/myjni.c
jint Java_com_my_fun_MyFunJNI_doFun(JNIEnv *env,jobject thiz){
    return c_fun();
}

Em seguida, coloque a biblioteca de programação myjni.c, como libmyfun.so, e coloque esta libmyfun.so e a biblioteca escrita em C em um local onde o programa java possa ser carregado quando for executado.

Desta forma, o programa java pode chamar o método da biblioteca desenvolvida por C. Na maioria dos casos, a segunda etapa da escrita do código é um trabalho chato de tradução de Java para C, especialmente quando envolve alguns tipos de trabalho de conversão. Se você não estiver familiarizado com a escrita, terá que verificar você mesmo ou copiá-lo de em outro lugar. Mas se o SWIG for usado, não precisamos escrever sozinhos os códigos relevantes na primeira e na segunda etapas, porque o SWIG pode gerá-los para nós. Portanto, acho que o que o SWIG faz é libertar você do trabalho “pesado, chato e sujeito a erros”.

 2. SWIG usa:

1) Suponha que o arquivo C/C++ que queremos empacotar seja o seguinte, denominado example.c:

#include <time.h>
 double My_variable = 3.0;
 
 int fact(int n) {
     if (n <= 1) return 1;
     else return n*fact(n-1);
 }
 
 int my_mod(int x, int y) {
     return (x%y);
 }
 	
 char *get_time()
 {
     time_t ltime;
     time(&ltime);
     return ctime(&ltime);
 }

2) Além disso, também precisamos definir um arquivo i de script de definição de interface (exemplo.i):

%module example
 %{
 /* Put header files here or function declarations like below */
 extern double My_variable;
 extern int fact(int n);
 extern int my_mod(int x, int y);
 extern char *get_time();
 %}
 
 extern double My_variable;
 extern int fact(int n);
 extern int my_mod(int x, int y);
 extern char *get_time();

3) Execute o comando SWIG para gerar o arquivo correspondente ao java:

swig -java example.i

Os dois arquivos java a seguir são gerados: 

Verificar:

public class example {
  public static void setMy_variable(double value) {
    exampleJNI.My_variable_set(value);
  }
  public static double getMy_variable() {
    return exampleJNI.My_variable_get();
  }
  public static int fact(int n) {
    return exampleJNI.fact(n);
  }
  public static int my_mod(int x, int y) {
    return exampleJNI.my_mod(x, y);
  }
  public static String get_time() {
    return exampleJNI.get_time();
  }
}
public class exampleJNI {
  public final static native void My_variable_set(double jarg1);
  public final static native double My_variable_get();
  public final static native int fact(int jarg1);
  public final static native int my_mod(int jarg1, int jarg2);
  public final static native String get_time();
}

Do ponto de vista JAVA, o encapsulamento da interface foi concluído, mas o método nativo precisa chamar a biblioteca dinâmica correspondente para empacotar por meio do comando a seguir. Observe que este é um ponto crítico. Os comandos a seguir não podem ser copiados, porque os comandos a seguir são compilados por meio da biblioteca dinâmica no diretório de inclusão do ambiente JAVA local e diferentes ambientes precisam ser alterados para caminhos adequados.

4) Compile com gcc:

gcc -c -fPIC example.c example_wrap.c -I/usr/lib/jvm/jdk-11.0.9/include -I/usr/lib/jvm/jdk-11.0.9/include/linux

Exemplo.o e exemplo_Wrap.o gerados

5) Gere uma biblioteca de link dinâmico:

gcc -shared -o example.so example.o example_wrap.o

exemplo gerado.so

6) Chame em java:

Copie os dois arquivos java (example.java e example_JNI.java) gerados pelo SWIG para o projeto java e então:

public class main {
   public static void main(String argv[]) {
     System.load("/home/kevin/Documents/Cpp/example.so");
     System.out.println(example.getMy_variable());
     System.out.println(example.fact(5));
     System.out.println(example.get_time());
   }
 }

Observe que também há armadilhas aqui. Existem duas maneiras de carregar a biblioteca dinâmica. Uma é carregar o arquivo no caminho absoluto por System.load e a outra é carregar o caminho padrão da biblioteca do sistema por System.loadLibrary .

Primeira experiência com SWIG - Zhihu

Acho que você gosta

Origin blog.csdn.net/liuxiao723846/article/details/131216385
Recomendado
Clasificación