Java SpringBoot引入C/C++庫(基于JNI)

獲取JNI頭文件

寫一個代表C++庫的接口的Java Class

package cn.task.service.jni;

public class JniTest {

    public JniTest() {
        // TODO Auto-generated constructor stub
    }

    static {
        System.loadLibrary("jniTest"); //jniTest就是要加載的動態(tài)庫的名字,這是相對路徑加載方式
    }

    public static native int demo_add(int a , int b);
    public static native String demo_print_string(String s);

}

將它轉化為class

 javac JniTest.java  

再轉化為JNI頭文件.h,注意這一步要在<projectName>/src/main/java的位置進行

 javah -classpath . -jni cn.task.service.jni.JniTest

得到如下頭文件cn_task_service_jni_JniTest.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class cn_ac_baqis_baqisCloud_task_service_jni_JniTest */

#ifndef _Included_cn_ac_baqis_baqisCloud_task_service_jni_JniTest
#define _Included_cn_ac_baqis_baqisCloud_task_service_jni_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     cn_task_service_jni_JniTest
 * Method:    demo_add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_cn_task_service_jni_JniTest_demo_1add
  (JNIEnv *, jclass, jint, jint);

/*
 * Class:     cn_task_service_jni_JniTest
 * Method:    demo_print_string
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_cn_task_service_jni_JniTest_demo_1print_1string
  (JNIEnv *, jclass, jstring);

#ifdef __cplusplus
}
#endif
#endif

打包并部署C++ library

C/C++庫要根據得到的頭文件的需要格式編寫

#include "cn_task_service_jni_JniTest.h"

JNIEXPORT jint JNICALL Java_cn_task_service_jni_JniTest_demo_1add
  (JNIEnv * env, jclass jc, jint a, jint b) {
      return a+b;
  }

JNIEXPORT jstring JNICALL Java_cn_task_service_jni_JniTest_demo_1print_1string
  (JNIEnv * env, jclass jc, jstring s) {
      return s;
  }

因為頭文件引用了jni.h,打包前需要找到你的jni.hjni_md.h的資源地址,一般是在JAVA資源路徑的include

我們在Java里想要調取的資源的名字是jniTest,所以我們希望生成名字為jniTest.dll(Windows)或libjniTest.so(Linux)的動態(tài)庫

Windows打包

gcc -fPIC -I "C:\Program Files\Java\jdk1.8.0_231\include" -I "C:\Program Files\Java\jdk1.8.0_231\include\win32" -shared -o jniTest.dll anyName.c

Windows上的JAVA默認會從當前文件夾內找資源,因此只要將動態(tài)庫放在當前項目內就可以被找到

Linux打包

生成.so,注意名字前必須加lib在可以在加載時被找到

gcc -fPIC -I /usr/lib/jvm/java-8-openjdk-amd64/include -I /usr/lib/jvm/java-8-openjdk-amd64/include/linux -shared -o libjniTest.so anyName.c

使用Linux時,為了可以在運行時被JAVA找到,我們還需要為我們的資源設置地址$LD_LIBRARY_PATH
打開 /etc/profile,寫入LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/helpers/native,并在終端輸入source /etc/profile啟用更新
將生成的.so庫放入/helpers/native,JAVA便會在運行時找到它,打包后的jar也可以成功找到它

Springboot中使用C/C++庫

寫一個Controller

package cn.task.controller;

import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.task.service.jni.JniTestService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@Controller
@Api(tags = "C++ Simulator internface")
@RequestMapping(value="/simulator")
public class JniTestController {

    @Resource
    @Autowired
    private JniTestService jniTestService ;

    @RequestMapping(value="/simulateAdd", method=RequestMethod.GET)
    @ApiOperation("Add to numbers")
    @ResponseBody
    public int simulateAdd( @RequestParam("a")int a,  @RequestParam("b")int b) {
        return jniTestService .demoAdd(a, b);
    }
    
    @RequestMapping(value="/simulatePrint", method=RequestMethod.GET)
    @ApiOperation("Print a String")
    @ResponseBody
    public String simulatePrint(@RequestParam("s")String s) {
        return  jniTestService .demoPrint(s);
    }
}

再寫一個處理Controller請求的Service,調用最早寫的C/C++庫的接口Class

package cn.task.service.jni;

import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class JniTestService {

    public static JniTest jni;
    
    public JniTestService () {
        // TODO Auto-generated constructor stub
    }

    public int demoAdd(int a, int b) {
        int i = jni.demo_add(a, b);
        return i;
    }
    
    public String demoPrint(String s) {
        String a = jni.demo_print_string(s);
        return a;
    }
}

啟動SpringBoot服務器,并向服務器發(fā)送請求


Swagger-UI demo
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容