专栏首页后端技术初学JNI java中调用c++的函数 helloworld实验

初学JNI java中调用c++的函数 helloworld实验

reference https://www.cnblogs.com/liuling/p/2013-12-20.html

简介

利用JNI可以让java的代码调用c/c++的代码。很多时候,某些功能用Java无法实现,这时候我们就可以利用JNI来调用C或者C++程序来实现。 比如说涉及到底层驱动的一些功能,这就是JNI的强大之处。

但是JNI也有它的缺点,使用java与本地已编译的代码交互,通常会丧失平台可移植性。

以下这个例子,是java调用c++输出hello world的例子。也是我根据博客做的实验的记录。

实验过程

第一步: 创建Java类,在里面定义一个native method

工程名为nativeTest, 类名为NativeTest

package nativeTest;

public class NativeTest {
    static {
        System.loadLibrary("Win32Project1");
    }

    public native void greeting();

    public static void main(String[] args) {
        new NativeTest().greeting();
    }
}

此处的Win32Project1所指的是Win32Project1.dll,我们此时还没生成,后面会生成。

第二步:用javah生成c++文件

进入工程所在目录,执行javah命令。 比如我的工程在C:\Users\Administrator\eclipse-workspace\nativeTest(工程名为nativeTest),该路径下的目录结构如下

nativeTest下的目录结构 那么进入该路径下的src文件夹, 在此执行 javah nativeTest.NativeTest

src下的目录结构, 执行后,在目录下会看到nativeTest_NativeTest.h, 这个头文件是根据包名和类名来命名的。 打开看到如下:

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

#ifndef _Included_nativeTest_NativeTest
#define _Included_nativeTest_NativeTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     nativeTest_NativeTest
 * Method:    greeting
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_nativeTest_NativeTest_greeting
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

通过extern "C"下方的注释我们可以知道,Java_nativeTest_NativeTest_greeting声明了一个方法,其类为nativeTest_NativeTest,方法名为greeting。 我们在native method里实现的方法的名字必须也是greeting

第三步:编写C/C++本地代码,生成动态链接库文件

在visual studio(或VC++)中创建dll项目。笔者用的是vs。

创建dll项目 笔者此时用的项目名为Win32Project1。所以你应该在目录中能看到Win32Project1.cpp。 请把上面生成的头文件nativeTest_NativeTest.h放在工程目录中(与Win32Project1.cpp在同一目录下),然后将其添加入项目。

项目结构 在Win32Project1.cpp中实现该函数。如下

// Win32Project1.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include <iostream>
#include "nativeTest_NativeTest.h"

using namespace std;

JNIEXPORT void JNICALL Java_nativeTest_NativeTest_greeting(JNIEnv *env, jobject obj)
{
    cout << "hello world!" << endl;
}

这里因为nativeTest_NativeTest.h中引入了jni.h,所以要将jni.h加入到vs安装目录下的VC/Include目录中。jni.h在JDK安装目录下的include中。 同时得将include/win32中的两个头文件jawt_md.h、jni_md.h也导入到vs中,放在同上的路径。 然后点生成-配置管理器,平台选x64

配置管理器

之后就能生成了。点击调试-生成解决方案。接着在项目目录下的x64/Debug能看到Win32Project1.dll。

然后我们将dll所在的路径加入环境变量path,这样链接时就能找得到了。

关于dll的名字,其实随便起都可以,如果是myDLL.dll,那调用时就写System.loadLibrary("myDLL");就好

最后,运行项目,得到运行结果

运行结果

意外:Can't load AMD 64-bit .dll on a IA 32-bit platform

总结

在该实验中,我们用cpp去实现greeting函数,让java调用它输出了hello world。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 张龙netty学习笔记 P10

    因为其请求-响应机制,聊天室是无法实现的。为了曲线救国,就出现了轮训技术,但不断的请求会造成带宽的浪费,而且不及时,而且header-body结构也会使请求报文...

    平凡的学生族
  • @Bean与@Component的比较

    我们知道@Bean是一个方法级别上的注解,主要用在@Configuration注解的类里,也可以用在@Component注解的类里。添加的bean的id为方法名...

    平凡的学生族
  • java nio 使用入门

    while循环中,多次channel.read(buffer)、flip并write后,如果不调用clear会使read返回0 跟踪read方法到IOUtil...

    平凡的学生族
  • 肿瘤类器官研究发展大事件

    2009年,荷兰Hubrecht研究所的Hans Clevers博士证实 肠干细胞 能够形成类器官,开启了 类器官研究的时代。 Nature Methods 如...

    生信技能树
  • RabbitMQ学习系列教程三:快速入门

    凯哥Java
  • Qt学习——分割窗口QSplitter类 .

    1.建立项目时基类选择QMainWindow,取消Gernerate form复选框的选中状态。

    bear_fish
  • 同学,Spring 是怎么解决循环依赖的?

    循环依赖其实就是循环引用,也就是两个或则两个以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于C,C又依赖于A。如下图:

    用户5224393
  • 每天一道leetcode-557反转字符串中的单词 III

    每天的题目见github(看最新的日期): https://github.com/gzc426

    乔戈里
  • 图像聚类的python实现

    因为之后的项目要用到影像聚类,之前一直是用ENVI实现,现在想学下python。 学习的这一篇:小项目聚类

    py3study
  • 【声明】前方不设坑位,不收费!~ 我为NET狂官方学习计划

    发个通知,过段时间学习计划相关的东西就出来了,上次写了篇指引文章后有些好奇心颇重的人跟我说:“发现最近群知识库和技能库更新的频率有点大,这是要放大招的节奏啊!”...

    逸鹏

扫码关注云+社区

领取腾讯云代金券