如何用SWIG封装c++接口给java使用?

SWIG是一种工具,用于将C/C++接口转换为多种编程语言,如Python、Java等,支持ISOC99和C++11-17特性。文章介绍了如何使用SWIG创建接口、生成代码并将其整合到Java项目中,包括使用JNI进行交互的示例。
摘要由CSDN通过智能技术生成

SWIG是什么?

SWIG(Simplified Wrapper and Interface Generator)是一个将C/C++接口转换为其他语言接口的工具,从而可以讲C/C++的库集成到其他语言的系统中。目前SWIG已经可以支持Python, Java, C#,Ruby,PHP,R语言等十多种语言。 

官方网址:

Simplified Wrapper and Interface Generatoricon-default.png?t=N7T8https://www.swig.org/

SWIG对c/c++语言特性的支持:

ISO C99全部特性, ISO C++ 从98到11 , 14, 17。 暂时还不支持C++20的特性

SWIG支持生成的语言:

  • C#
  • D
  • Go
  • Guile
  • Java
  • Javascript
  • Lua
  • MzScheme/Racket
  • OCaml
  • Octave
  • Perl
  • PHP
  • Python
  • R
  • Ruby
  • Scilab
  • Tcl

支持的平台

Unix,windows,Mac都支持。

SWIG如何使用?

1.编写swig的interface文件,指明接口的内容

2.用swig程序生成对应的接口代码

3.用gcc/g++编译生成的接口代码, 以及对应语言的代码

4.对目标语言调用接口

下面我给结合Demo.

这个Demo将cpp的代码接口转化为JAVA的代码接口。

cpp代码:

apple.h

#ifndef __APPLE_H__
#define __APPLE_H__


enum class LogLevel {
    Trace  /// Most detailed output
    ,Debug
    ,Info
    ,Warn
    ,Error
    ,Fatal  /// Least detailed output
    ,Current  /// no-op, value indicates current level should be retained
};


class Apple
{
public:
    Apple();
    int GetColor(void);
    void SetColor(int color);
    
private:
    int m_nColor;
};
#endif 

apple.cpp

#include "apple.h"

Apple::Apple() : m_nColor(0)
{
}
 
void Apple::SetColor(int color)
{
    m_nColor = color;
}
 
int Apple::GetColor(void)
{
    return m_nColor;
}

SWIG接口文件 apple.i

%module demo
%{
/* Includes the header in the wrapper code */
#include "apple.h"
%}

/* Parse the header file to generate wrappers */
%include "apple.h"

用SWIG生成代码

swig -java -c++ apple.i

swig会生成好几个文件:

demo.java,    module名称

Apple.java,   类的实现

apple_wrap.cxx , c++的接口

demoJNI.java , JNI的接口

编译C++的接口

生成libapple_java.so 

在这个so中直接将apple.o也包含进来了。

g++ -fpic -shared apple_wrap.cxx  -o libapple_java.so   apple.o  \
-I/usr/lib/jvm/default-java/include \
-I/usr/lib/jvm/default-java/include/linux

java代码测试:

编写测试代码main.java

public class main {
  public static void main(String argv[]) {
    System.loadLibrary("apple_java");
    
    Apple a = new Apple();
    a.SetColor(1);
    System.out.println(a.GetColor());

  }
}


编译运行java代码

javac main.java
java -Djava.library.path=.  main
1

#输出1

OK,输出1,运行成功。


SWIG生成的代码都有什么?

让我们看一看swig生成的代码都有什么东西。

不需要我们一个一个手写是有多爽。

apple_wrap.cxx 内容有点长,327行,我们只放核心内容。

基本上就是把Apple这个class里面的接口都给重新封装了一个函数,在这些函数里面调用了一下原来Apple自己的函数。

#ifndef SWIGEXPORT
# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
#   if defined(STATIC_LINKED)
#     define SWIGEXPORT
#   else
#     define SWIGEXPORT __declspec(dllexport)
#   endif
# else
#   if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)
#     define SWIGEXPORT __attribute__ ((visibility("default")))
#   else
#     define SWIGEXPORT
#   endif
# endif
#endif

#include <jni.h>
#include <stdlib.h>
#include <string.h>


SWIGEXPORT jlong JNICALL Java_demoJNI_new_1Apple(JNIEnv *jenv, jclass jcls) {
  jlong jresult = 0 ;
  Apple *result = 0 ;
  
  (void)jenv;
  (void)jcls;
  result = (Apple *)new Apple();
  *(Apple **)&jresult = result; 
  return jresult;
}


SWIGEXPORT jint JNICALL Java_demoJNI_Apple_1GetColor(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
  jint jresult = 0 ;
  Apple *arg1 = (Apple *) 0 ;
  int result;
  
  (void)jenv;
  (void)jcls;
  (void)jarg1_;
  arg1 = *(Apple **)&jarg1; 
  result = (int)(arg1)->GetColor();
  jresult = (jint)result; 
  return jresult;
}


SWIGEXPORT void JNICALL Java_demoJNI_Apple_1SetColor(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2) {
  Apple *arg1 = (Apple *) 0 ;
  int arg2 ;
  
  (void)jenv;
  (void)jcls;
  (void)jarg1_;
  arg1 = *(Apple **)&jarg1; 
  arg2 = (int)jarg2; 
  (arg1)->SetColor(arg2);
}


SWIGEXPORT void JNICALL Java_demoJNI_delete_1Apple(JNIEnv *jenv, jclass jcls, jlong jarg1) {
  Apple *arg1 = (Apple *) 0 ;
  
  (void)jenv;
  (void)jcls;
  arg1 = *(Apple **)&jarg1; 
  delete arg1;
}

当然,也不能少了 java代码。 

Apple.java 的内容

/* ----------------------------------------------------------------------------
 * This file was automatically generated by SWIG (http://www.swig.org).
 * Version 4.0.1
 *
 * Do not make changes to this file unless you know what you are doing--modify
 * the SWIG interface file instead.
 * ----------------------------------------------------------------------------- */


public class Apple {
  private transient long swigCPtr;
  protected transient boolean swigCMemOwn;

  protected Apple(long cPtr, boolean cMemoryOwn) {
    swigCMemOwn = cMemoryOwn;
    swigCPtr = cPtr;
  }

  protected static long getCPtr(Apple obj) {
    return (obj == null) ? 0 : obj.swigCPtr;
  }

  @SuppressWarnings("deprecation")
  protected void finalize() {
    delete();
  }

  public synchronized void delete() {
    if (swigCPtr != 0) {
      if (swigCMemOwn) {
        swigCMemOwn = false;
        demoJNI.delete_Apple(swigCPtr);
      }
      swigCPtr = 0;
    }
  }

  public Apple() {
    this(demoJNI.new_Apple(), true);
  }

  public int GetColor() {
    return demoJNI.Apple_GetColor(swigCPtr, this);
  }

  public void SetColor(int color) {
    demoJNI.Apple_SetColor(swigCPtr, this, color);
  }

}

还有这个 JNI的定义,这就是常见的JNI定义的方式了。

demoJNI.java


public class demoJNI {
  public final static native void vv_set(long jarg1);
  public final static native long vv_get();
  public final static native long new_Apple();
  public final static native int Apple_GetColor(long jarg1, Apple jarg1_);
  public final static native void Apple_SetColor(long jarg1, Apple jarg1_, int jarg2);
  public final static native void delete_Apple(long jarg1);
}

到这里你基本上就学会了如何将C++封装成JAVA。

但是还差一步,一般的java代码都是提供jar的,有些还提供多个操作系统的.so供外部调用。

java的JNI封装成jar

这一块大家可以参考:

GitHub - opentdf/client-java: Java wrapper for client-cpp core library for OpenTDF

大概是用pom.xml,将.so封装在jar里面。

加载时用的是native-lib-loader根据操作系统的不同选择不同的.so

熟悉java的可以看一下,应该也很简单。

  <dependencies>
    <dependency>
      <groupId>org.scijava</groupId>
      <artifactId>native-lib-loader</artifactId>
      <version>2.1.4</version>
    </dependency>
  </dependencies>

### 回答1: SWIG是一个用于连接C/C++和其他编程语言的工具。它提供了一种简单的方式,可以通过自动生成中间代码来实现C/C++的功能与其他编程语言(如Java)之间的交互。 通过SWIG,我们可以将C代码转换为Java代码,并在Java中调用C库中的函数。这样做的好处是可以利用C/C++的高性能、底层控制和已有的库文件,并在Java使用这些功能。 要将C代码转换为Java代码,我们需要这样做的步骤: 1. 创建一个SWIG接口文件,以描述C函数的输入和输出类型。这个接口文件使用SWIG定义的特定语法。 2. 使用SWIG运行器,将接口文件作为输入,并生成一个Java包含C函数的Java接口文件。 3. 创建Java代码,以断开连接的方式调用生成的Java接口文件中的C函数。 SWIG通过将C代码封装在JNI(Java Native Interface)调用中来实现C与Java的交互。这允许Java代码直接调用C代码,并从C代码中返回结果。 使用SWIG进行C到Java转换可以使开发人员更加方便地利用两种语言的优点,提高开发效率和性能。SWIG还支持其他编程语言,如Python、Ruby和Perl,使C代码更容易与这些语言进行交互。 总之,SWIG是一个非常有用的工具,可以帮助在C/C++Java之间实现无缝的交互,为开发人员提供了更多的灵活性和选择,并最大程度地利用现有的代码和库文件。 ### 回答2: Swig是一个开源工具,用于将C/C++代码转换为支持多种编程语言的代码,包括Java使用Swig可以很方便地将C代码转换为Java代码。 转换C代码为Java需经过以下步骤: 1. 安装Swig:首先需要安装Swig工具,可以从Swig官方网站下载并按照指示进行安装。 2. 编写接口文件:接口文件是一个后缀名为.i的文件,用于定义需要转换的C代码和Java代码的映射关系。在接口文件中,需要指定需要转换的C函数的签名以及导出到Java的类、方法、成员变量等。 3. 生成包装代码:使用Swig生成器来生成C和Java代码的包装代码。通过运行类似以下命令来生成包装代码: ``` swig -java your_interface.i ``` 4. 编译和构建:在生成的C代码中,使用Java Native Interface(JNI)来与Java代码进行交互。使用C/C++编译器将C代码编译为共享库(.so或.dll文件),以供Java程序调用。 5. 构建Java代码:创建Java项目,在项目中引入包装代码并实现调用。可以使用JNI函数调用C函数,或直接使用包装代码生成的Java类和方法进行调用。 需要注意的是,转换C代码到Java并不是一种直接的转换过程,可能存在一些依赖问题,对于一些复杂的C代码或使用了C特定功能的代码,还需要在Java代码中添加适当的兼容性处理。 总结而言,Swig是一个强大的工具,可以将C代码转换为Java代码,简化了C/C++Java之间的交互过程,提高了代码的可维护性和可扩展性。 ### 回答3: SWIG(Simplified Wrapper and Interface Generator)是一个用于将C/C++代码转换为其他语言的工具。如果想要将C代码转换为Java代码,可以使用SWIG来完成。 首先,在使用SWIG之前,需要确保已经安装好了SWIG,并且配置好了相关的环境变量。 接下来,需要创建一个包含C代码的接口文件,该文件的后缀名通常为.i。在接口文件中,需要使用SWIG的语法来指定要转换的C函数和类型。 然后,使用SWIG命令对接口文件进行处理,以生成Java代码。命令的语法通常为:swig -java interfacefile.i 完成上述操作后,会生成一系列的Java文件,包括接口文件中指定的函数和类型的Java封装类。 最后,可以将生成的Java代码导入到你的项目中,并与其它Java代码一起进行编译和运行。 需要注意的是,SWIG并非完美的工具,可能会有一些限制和问题。在使用SWIG进行C转Java时,可能会遇到一些类型对应的困难,或者在C和Java之间的内存管理方面的差异。因此,在使用SWIG转换代码时,需要谨慎处理这些问题,并进行相应的修改和调试。 总之,通过使用SWIG,我们可以方便地将C代码转换为Java代码,从而能够在Java平台上使用C语言的功能和库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路边闲人2

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值