01.Jni开发流程_java调用C/C++

简介: (创建于2017/11/18)JNI(Java Native Interface)Java调用C/C++,C/C++调用Java的一套API1.编写native方法public class JniUtils { public stati...

(创建于2017/11/18)

JNI(Java Native Interface)
Java调用C/C++,C/C++调用Java的一套API

1.编写native方法

public class JniUtils {
    public static native String getStringFromC();
    public native String getStringFromC2();
}

2.javah命令,生成.h头文件

cd 进入到src目录下,使用命令生成头文件 javah 包名+类型(如 com.renzhenming.utils.JniUtils)

3.复制.h头文件到CPP工程中

右键->添加现有项->将头文件添加到vs中的头文件目录中,不要直接复制,直接复制无效

4.复制jni.h和jni_md.h文件到CPP工程中

发现在我们生成的头文件中有对jni.h 的导入,jni.h中又有对jni_md.h的导入,所以我们直接去jdk目录下搜索道这两个头文件,引入到工程中,同样是添加现有项
注意include的时候,<>与“”的灵活使用,假设生成的头文件是这样的(有时候Javah命令生成的头文件中没有方法名,只有一些预编译的东西,不知何故)

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

#ifndef _Included_com_renzhenming_bsdiff_JniUtils
#define _Included_com_renzhenming_bsdiff_JniUtils
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_renzhenming_bsdiff_JniUtils
 * Method:    getStringFromC
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_renzhenming_bsdiff_JniUtils_getStringFromC
  (JNIEnv *, jclass);

/*
 * Class:     com_renzhenming_bsdiff_JniUtils
 * Method:    getStringFromC2
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_renzhenming_bsdiff_JniUtils_getStringFromC2
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

5.实现.h头文件中声明的函数

假设如上边一样,我们生成了头文件,那么我们需要在自己的c文件中定义实现这两个方法

#include "com_renzhenming_bsdiff_JniUtils.h"    //引入头文件

JNIEXPORT jstring JNICALL Java_com_renzhenming_bsdiff_JniUtils_getStringFromC
(JNIEnv *env, jclass jcls) {
    return (*env)->NewStringUTF(env, "aaaaaaa");  //得到字符串
}

JNIEXPORT jstring JNICALL Java_com_renzhenming_bsdiff_JniUtils_getStringFromC2
(JNIEnv *env, jobject jobj) {
    return (*env)->NewStringUTF(env, "bbbbbb");//得到字符串
}

6.visual studio生成dll文件


img_34b78a9c2dfcbc0c22dc5d0d7b62af4b.png
37761343.png

如上点击debug出现下拉框,选择配置管理器,将我们的活动解决方案设置为x64


img_89df1598f30f5d29b5043162942d7af0.png
37833718.png

右键项目名->属性,设置常规下的项目默认值下的配置类型选择动态库(.dll),然后
img_d2c374a5b964ba33d9190922e4c06657.png
37905203.png

点击生成,选择生成解决方案,这时候我们的dll动态库就生成在指定目录中了


img_8963a5a8598867b94a5f29a6519bdea4.png
37963765.png

7.vs生成dll动态库的时候容易出现的问题和解决方法
1.使用了过时的函数

严重性 代码  说明  项目  文件  行   禁止显示状态
错误  C4996   'open': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _open. See online help for details. ndk_update  c:\users\renzhenming\documents\visual studio 2015\projects\ndk_update\ndk_update\bsdiff.cpp 263 
    
解决办法:给所在的类添加宏定义
define _CRT_NONSTDC_NO_DEPRECATE
或者给整个项目添加右键项目名->属性->配置属性->c/c++->命令行,在其他选项中添加 -D _CRT_NONSTDC_NO_DEPRECATE,确定即可,这样会给整个项目设置这个配置,不再需要在每个类中分别添加了
2.使用了不安全的函数

严重性 代码  说明  项目  文件  行   禁止显示状态
错误  C4996   'open': This function or variable may be unsafe. Consider using _sopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. ndk_update  c:\users\renzhenming\documents\visual studio 2015\projects\ndk_update\ndk_update\bsdiff.cpp 263 
    
解决办法:同上的方式添加宏定义,_CRT_SECURE_NO_WARNINGS
3.安全性检查相关的问题

bsdiff是外国程序员写的,可能使用的工具不是vs,而vs对代码安全性检查比较严格,所以导致这个问题
在linux系统下不会报这个错误

严重性 代码  说明  项目  文件  行   禁止显示状态
错误  C4703   使用了可能未初始化的本地指针变量“old”   ndk_update  c:\users\renzhenming\documents\visual studio 2015\projects\ndk_update\ndk_update\bsdiff.cpp 266 
错误  C4703   使用了可能未初始化的本地指针变量“V” ndk_update  c:\users\renzhenming\documents\visual studio 2015\projects\ndk_update\ndk_update\bsdiff.cpp 273 
错误  C4703   使用了可能未初始化的本地指针变量“_new”  ndk_update  c:\users\renzhenming\documents\visual studio 2015\projects\ndk_update\ndk_update\bsdiff.cpp 295 
    
解决办法:右键项目名->属性->配置属性->c/c++->常规->SDL检查选择否
4.重复引用的问题

这个错误的原因是因为项目中既添加了bsdiff.cpp也添加了bspatch.cpp文件,导致出现定义的重复问题
也就是二者不可同时存在,移除一个

严重性 代码  说明  项目  文件  行   禁止显示状态
错误  LNK2005 "void __cdecl err(int,char const *)" (?err@@YAXHPEBD@Z) 已经在 bsdiff.obj 中定义  ndk_update  c:\Users\renzhenming\Documents\Visual Studio 2015\Projects\ndk_update\ndk_update\bspatch.obj    1   
错误  LNK2005 "void __cdecl errx(int,char const *)" (?errx@@YAXHPEBD@Z) 已经在 bsdiff.obj 中定义    ndk_update  c:\Users\renzhenming\Documents\Visual Studio 2015\Projects\ndk_update\ndk_update\bspatch.obj    1   
错误  LNK1169 找到一个或多个多重定义的符号  ndk_update  c:\Users\renzhenming\Documents\Visual Studio 2015\Projects\ndk_update\x64\Debug\ndk_update.exe  1   
    
解决办法:针对这个项目的编译,不要让两者同时存在
相关文章
|
jenkins Shell 测试技术
|
安全 jenkins Java
Java、Python、C++支持jenkins和SonarQube(一)
Jenkins 是一个开源的 持续集成(CI)和持续交付(CD) 工具,用于自动化构建、测试和部署软件项目。它基于 Java 开发,支持跨平台运行,并拥有丰富的插件生态系统,可以灵活地扩展功能
669 5
|
jenkins Java Shell
Java、Python、C++支持jenkins和SonarQube(全集)
Jenkins 是一个开源的持续集成(CI)和持续交付(CD)工具,用于自动化构建、测试和部署软件项目。它基于 Java 开发,支持跨平台运行,并拥有丰富的插件生态系统,可以灵活地扩展功能
988 1
|
jenkins Java 持续交付
Java、Python、C++支持Jenkins和SonarQube(三)
Python与Jenkins和SonarQube
611 1
|
jenkins Java 测试技术
|
算法 Java 数据库连接
Java 与 C++ 区别深入剖析及应用实例详解
本文深入剖析了Java和C++两种编程语言的区别,从编译与执行机制、面向对象特性、数据类型与变量、内存管理、异常处理等方面进行对比,并结合游戏开发、企业级应用开发、操作系统与嵌入式开发等实际场景分析其特点。Java以跨平台性强、自动内存管理著称,适合企业级应用;C++则因高性能和对硬件的直接访问能力,在游戏引擎和嵌入式系统中占据优势。开发者可根据项目需求选择合适语言,提升开发效率与软件质量。附面试资料链接:[点此获取](https://pan.quark.cn/s/4459235fee85)。
1157 0
|
Java Android开发 C++
Java和C++
Java和C++
458 15
|
IDE Java 程序员
C++ 程序员的 Java 指南
一个 C++ 程序员自己总结的 Java 学习中应该注意的点。
277 5
WK
|
安全 Java 编译器
C++和Java哪个更好用
C++和Java各具优势,选择取决于项目需求、开发者偏好及目标平台特性。C++性能出色,适合游戏、实时系统等;Java平台独立性强,适合跨平台、安全敏感应用。C++提供硬件访问和灵活编程范式,Java有自动内存管理和丰富库支持。两者各有千秋,需根据具体需求选择。
WK
683 1
|
安全 Java API
【性能与安全的双重飞跃】JDK 22外部函数与内存API:JNI的继任者,引领Java新潮流!
【9月更文挑战第7天】JDK 22外部函数与内存API的发布,标志着Java在性能与安全性方面实现了双重飞跃。作为JNI的继任者,这一新特性不仅简化了Java与本地代码的交互过程,还提升了程序的性能和安全性。我们有理由相信,在外部函数与内存API的引领下,Java将开启一个全新的编程时代,为开发者们带来更加高效、更加安全的编程体验。让我们共同期待Java在未来的辉煌成就!
506 11