您的位置 首页 java

Java调用C++程序过程及问题解决

1、Java调用C++程序过程

Java作为一种跨平台语言,通过虚拟机的机制能够很好的将代码迁移到各个平台,但是有时候需要调用平台底层的功能,这时候往往需要利用C/C++语言进行底层代码的编写以达到很好的性能。那如何使Java能够方便的调用C/C++程序呢?本文将以一个“hello Word”基础程序给你讲解如何利用Java调用C++程序(该技术称为JNI技术)。其主要过程包括5步骤:1、编写Java本地调用程序;2、对Java程序进行编译;3、编写C/C++实现代码;4、生成动态库(dll);5、进行调用。

1.1 编写Java本地调用程序

先上代码,如下所示:

 public class JNITest {
    static {
        System.loadLibrary("JNITest");  // 1、定义需要加载的dll库名称
    }

    public static native void sayHelloWorld(String msg); // 2、利用native关键字定义调用接口

    public static void main(String[] args) {
        sayHelloWorld("Hello, world");  // 3、在主方法中进行调用
    }

}  

主要包含3个部分,首先通过System.loadLibrary()方法进行dll文件的声明,让Java程序知道需要加载哪个dll文件;其次利用native关键字定义Java调用C/C++语言的接口,该接口将由C/C++进行具体实现,注意在方法前一定要标注native关键字,因为利用native关键字标注的方法,让Java虚拟知道该方法的实现是由外部程序实现,而不是由Java程序实现;最后为了方便后面的调试,需要定义一个主方法并对sayHelloWorld进行调用。

1.2 对Java程序进行编译

在Windows系统通过菜单键+R并输入cmd命令,调出命令行窗口,并通过cd命令,将执行目录切换到1.1步骤中java文件所在的文件目录中。然后在命令行中输入javac JNITest.java对该java文件进行编译,如下图所示:

Java程序进行编译

在这个过程中需要注意两点问题,首先JDK的路径是否加入到系统的环境变量中;其次如果java文件带有包地址,需要将java文件的包地址写上。

输入上述命令后,在java文件所在的目录下将生成JNITest.class文件,该文件就是编译后的文件。然后在命令行中输入javah JNITest将生成C/C++的头文件(JNITest.h),如下图所示:

生成头文件

 /* DO NOT EDIT THIS FILE - it is machine generated */#include jni.h
/* Header for class JNITest */#ifndef _Included_JNITest
#define _Included_JNITest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     JNITest
 * Method:    sayHelloWorld
 * Signature: (Ljava/lang/String;)V
 */JNIEXPORT void JNICALL Java_JNITest_sayHelloWorld
  (JNIEnv *, jclass, jstring);
#ifdef __cplusplus
}
#endif
#endif  

从上面的代码可以看出在JNITest.h文件中定义了java中的native接口。

1.3 编写C/C++实现代码

首先在vs2019 “文件-》新建-》项目”中创建C++动态程序,其创建过程如下图所示:

新建dll库

然后在右侧的项目中点击“源文件”并鼠标右键,依次选择“添加-新建项”,将弹出如下界面,并选择“C++文件”,来创建空白C++文件。

创建新的C++文件

再然后将JNITest.h中的声明方法拷贝到该文件中并实现具体的实现。代码如下图所示:

 #include "pch.h"
#include "JNITest.h"   // 1.申明引用的头文件,该头文件就是用javah生成的头文件

// 2.该方法申明,必须要与JNITest中的声明一致,
JNIEXPORT void JNICALL Java_JNITest_sayHelloWorld    
(JNIEnv *env, jclass, jstring string) {
// 3.具体实现,获取java传过来的参数进行输出
const char* str = env->GetStringUTFChars(string, 0);
char cap[128];
strcpy_s(cap, str);
//env->ReleaseStringUTFChars(string, str);
printf(str);
}  

然后,在VS2019右边的项目目录中点击“头文件”鼠标右键,并依次点击“添加-》现有项”,将用javah生成的JNITest.h头文件添加到项目中,添加后如下图所示:

1.4 生成动态库(dll

编写好代码后,在vs2019右边的项目目录中,点击项目名称,并点击鼠标右键,在弹出的选择框中选择“生成”对代码进行编译。编译成功后,将会在项目的debug文件下生成相应的dll文件,其余文件不用管。如下图所示:

生成dll结果

1.5 进行调用

将1.4中生成的dll拷贝到1.1中的java文件夹下,并将dll文件的名称更改为JNITest(该名称需要与System.loadLibrary()一致),然后在命令行中输入“java JNITest”,将出现如下结果,说明调用成功。

进行调用

2、出现的问题及解决过程

在实际的开发过程中,出现了两种问题,现将遇到的问题及解决方法,与大家进行分享。

1、报错无法找到jni文件

在C/C++程序进行编译的过程,出现如下的编译错误,如下图所示:

这说明vs环境未能找到jni.h头文件,该头文件存在与你JDK的include文件夹中,但是该jni.h还引用其他文件,为了保险起见,需要将jdk中的include文件夹和该文件夹下的window32文件夹加入到当前的项目中,具体的操作为,在vs2019右侧的项目目录中点击项目名,并鼠标右键,选择“属性”,弹出如下对话框:

在包含目录中添加jdk相应的路径,如下图所示:

然后进行重新编译即可。

2、在进行java调用时,出现Can’t load IA 32-bit .dll on a AMD 64-bit platform错误

这是由于你生成的dll是32位的,然而Java的jdk是64位的导致的。解决方法,有两种方法,一种是更换jdk版本变更成32位的;另一种采用X64重新对dll进行编译,其具体的操作过程为:1、在vs2019顶部选择“生成-》配置管理器”,如下图所示:

在上图中“平台”选项中选择正确的平台,然后进行重新编译,即可解决该类问题。

文章来源:智云一二三科技

文章标题:Java调用C++程序过程及问题解决

文章地址:https://www.zhihuclub.com/183536.shtml

关于作者: 智云科技

热门文章

网站地图