Introducción y uso de SWIG

Sitio web oficial: https://www.swig.org/ github: https://github.com/swig

SWIG es una herramienta de desarrollo de software que interconecta programas escritos en C y C++ con varios lenguajes de programación de alto nivel.

SWIG funciona con diferentes tipos de lenguajes de destino, incluidos lenguajes de programación comunes como Javascript, Perl, PHP, Python, Tcl y Ruby. La lista de lenguajes admitidos también incluye lenguajes que no son de secuencias de comandos, como C#, D, el lenguaje Go, Java, incluidos Android, Lua, OCaml, Octave, Scilab y R. También se admiten varias implementaciones de Scheme interpretadas y compiladas (Guile, MzScheme/Racket). SWIG se utiliza más comúnmente para crear entornos de programación compilados o interpretados de alto nivel, interfaces de usuario y como herramienta para probar y crear prototipos de software C/C++. SWIG se utiliza normalmente para analizar la interfaz C/C++ y generar el "código adhesivo" necesario para que el lenguaje de destino anterior llame al código C/C++. SWIG también puede exportar su árbol de análisis como XML. SWIG es software gratuito y el código generado por SWIG es compatible con proyectos comerciales y no comerciales.

Descargar e instalar:

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

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

1. Trago para Java:

Sitio web oficial: SWIG y Java

Las extensiones Java de SWIG hacen que sea muy fácil acceder al código C/C++ existente desde Java porque SWIG escribe el código de la interfaz nativa de Java (JNI) por usted. Se diferencia del uso de la herramienta "javah" porque SWIG empaquetará el código C/C++ existente, mientras que javah toma declaraciones de funciones Java "nativas" y crea prototipos de funciones C/C++. SWIG envuelve código C/C++ con clases de proxy Java, lo cual es útil si desea acceder a una gran cantidad de código C/C++ desde Java. Usar SWIG puede resultar excesivo si solo necesita una o dos funciones JNI. SWIG permite que los programas Java llamen fácilmente al código C/C++ desde Java. Históricamente, SWIG no podía generar ningún código para llamar código Java desde C++. Sin embargo, SWIG ahora admite polimorfismo completo entre lenguajes y genera código para llamar desde C++ a Java al empaquetar un método virtual de C++.

LightGBM4j: un contenedor de Java para LightGBM, utilizando SWIG.

https://github.com/metarank/lightgbm4j

1) La diferencia entre SWIG y JNA:

2) ¿Qué puede hacer SWIG para Java?

SWIG sirve para generar código intermedio para otros lenguajes de programación que pueden llamar a bibliotecas escritas en C y C++. Por ejemplo, si sabe que Java puede llamar a C y C++ a través de JNI, entonces SWIG está "haciendo cosas JNI".

Aquí hay una explicación de "hacer cosas JNI": cuando desarrollamos Java, en algunos casos necesitamos llamar a una biblioteca desarrollada por C. Pero no hay forma de que el código Java llame directamente a la biblioteca desarrollada por C. Debe desarrollarse en aproximadamente dos pasos:

En el primer paso, debe escribir un código de capa Java, cargar la biblioteca so y declarar un método nativo:

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

En el segundo paso, debe escribir un código de capa C correspondiente al método doFun en el primer paso MyFunJNI y llamar a la función int c_fun() en la biblioteca C que desea usar:

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

Luego coloque la biblioteca de programación myjni.c, como libmyfun.so, y coloque este libmyfun.so y la biblioteca escrita en C en una ubicación donde se pueda cargar el programa Java cuando se ejecute.

De esta forma, el programa java puede llamar al método en la biblioteca desarrollada por C. En la mayoría de los casos, el segundo paso de la codificación es un trabajo aburrido de traducir de Java a C, especialmente cuando implica algunos tipos de trabajo de conversión. Si no está familiarizado con la escritura, debe verificarla usted mismo o copiarla de otro lugar. . Pero si se usa SWIG, no necesitamos escribir los códigos relevantes en el primer y segundo paso nosotros mismos, porque SWIG puede generarlos por nosotros. Por lo tanto, creo que lo que hace SWIG es liberarte del trabajo "pesado, aburrido y propenso a errores".

 2. TRAGO usos:

1) Supongamos que el archivo C/C++ que queremos empaquetar es el siguiente, llamado ejemplo.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) Además, también necesitamos definir un archivo i de script de definición de interfaz (ejemplo.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) Ejecute el comando SWIG para generar el archivo correspondiente a java:

swig -java example.i

Se generan los siguientes dos archivos java: 

Controlar:

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();
}

Desde la perspectiva de JAVA, la encapsulación de la interfaz se ha completado, pero el método nativo necesita llamar a la biblioteca dinámica correspondiente para empaquetar mediante el siguiente comando. Tenga en cuenta que este es un punto crítico. Los siguientes comandos no se pueden copiar porque los siguientes comandos se compilan a través de la biblioteca dinámica en el directorio de inclusión del entorno JAVA local y es necesario cambiar diferentes entornos a rutas adecuadas.

4) Compilar con 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

Ejemplo.o y ejemplo_Wrap.o generados

5) Generar una biblioteca de enlaces dinámicos:

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

ejemplo generado.so

6) Llamar en java:

Copie los dos archivos java (example.java y example_JNI.java) generados por SWIG al proyecto java, luego:

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());
   }
 }

Tenga en cuenta que aquí también hay trampas: hay dos formas de cargar la biblioteca dinámica: una es cargar el archivo en la ruta absoluta a través de System.load y la otra es cargar la ruta predeterminada de la biblioteca del sistema a través de System.loadLibrary. .

Primera experiencia con SWIG - Zhihu

Supongo que te gusta

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