这里需要思考一个问题:
作为一个java程序员,对于String自然是很熟,java去调C++/C,因为java是字符串是对象,而对于C来说字符串则是字符指针,约定以00结尾结束字符串。C++对于字符串也可以和java一样直接""
表示
JNI的方式,java将字符串传C++,然后返回一个新的字符串 示例:
定义java的native方法
package top.yumbo.jni;
public class JavaCallCpp{
public native String doXXX(String str);
}
提示:头文件或者环境问题,看下 前面的 JNI helloworld 案例
在src下打开终端,通过javac -h ./ .\top\yumbo\jni\JavaCallCpp.java
得到头文件,为了偷懒直接将头文件后缀改成.cpp
文件,
然后直接将函数声明的分号去掉写函数体的实现
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class top_yumbo_jni_JavaCallCpp */
#ifndef _Included_top_yumbo_jni_JavaCallCpp
#define _Included_top_yumbo_jni_JavaCallCpp
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: top_yumbo_jni_JavaCallCpp
* Method: doXXX
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_top_yumbo_jni_JavaCallCpp_doXXX
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
如下是写好后的cpp文件,加入了头文件string.h
用于处理字符串
注意规范,因为文件是java自动生成的,会根据包路径,类目,方法名生成,只需要改生产的方法即可
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <string.h>
/* Header for class top_yumbo_jni_JavaCallCpp */
#ifndef _Included_top_yumbo_jni_JavaCallCpp
#define _Included_top_yumbo_jni_JavaCallCpp
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: top_yumbo_jni_JavaCallCpp
* Method: doXXX
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_top_yumbo_jni_JavaCallCpp_doXXX
(JNIEnv *env, jobject obj, jstring str) {
// jint就是C中的long类型,通过宏定义定义的,故下面的循环可以用
jint len = env->GetStringUTFLength(str);
const char * chs = env->GetStringUTFChars(str, 0);
char* chs2=new char[100];
strcpy(chs2,chs);
for (int i = 0; i < len; ++i) {
chs2[i]+=1;
}
return env->NewStringUTF(chs2);
}
#ifdef __cplusplus
}
#endif
#endif
写好后进行编译成dll
需要将我们写好的cpp文件通过add_library
加进去才会进行编译,具体看 前面的HelloWorld案例
cmake_minimum_required(VERSION 3.17)
project(JHelloWorld)
set(CMAKE_CXX_STANDARD 20)
# add_executable(jni ${SOURCE_FILES})
add_library(
JHelloWorld
SHARED
top_yumbo_jni_JavaCallCpp.cpp
)
target_link_libraries(JHelloWorld)
Build -> build project 即可生成编译的dll文件,copy到java项目中,之前写java类的地方
package top.yumbo.jni;
public class JNIDemo {
public static void main(String[] args) {
// 加载dll
System.loadLibrary("src/top/yumbo/jni/lib/libJHelloWorld");
// 创建之前定义的java类对象
JavaCallCpp javaCallCpp = new JavaCallCpp();
// 调用一下native方法,调用前面通过c写好的方法,将abcdef 的每一个字符+1
// 根据asccii码定义,也就会变成bcdefg
String str = javaCallCpp.doXXX("abcdef");
// 将返回的内容打印出来
System.out.println(str);
}
}
结果如下,值也是我们预期的值。