【混合编程JNI】之第一篇 Hello world

举报
香菜聊游戏 发表于 2022/06/26 21:21:21 2022/06/26
【摘要】 第一篇混合编程的文章,废话不多说,直接走起。因为是第一篇文章,所以还是慢慢来。Jni 是什么JNI全称为Java Native Interface,即Java本地接口。通过JNI可以使得Java与C/C++进行交互。即可以在Java代码中调用C/C++代码或者在C/C++代码中调用Java代码。因为JNI是JVM规范的一部分,因此可以将我们写的JNI的程序在任何Java虚拟机中运行。JNI的...

第一篇混合编程的文章,废话不多说,直接走起。

因为是第一篇文章,所以还是慢慢来。

Jni 是什么

JNI全称为Java Native Interface,即Java本地接口。通过JNI可以使得Java与C/C++进行交互。即可以在Java代码中调用C/C++代码或者在C/C++代码中调用Java代码。

因为JNI是JVM规范的一部分,因此可以将我们写的JNI的程序在任何Java虚拟机中运行。

JNI的这个方式让我们可以复用以前的C/C++代码,JNI是一种在Java虚拟机机制下的执行代码的标准机制。

官方文档

学习的话首先是看下官方的文档,在官网搜索了半天找到下面的网址,中间的曲折就不说了,都是泪!!!

Java Native Interface Specification Contents

image.png

英语好的话可以直接看上面的文档,英语不好的话就看下我下面的总结

我增加了一些例子,可能更好理解吧,OK ,开始吧

混合编程主要流程

混合语言编程的话,总有一个主要的语言,也就是启动语言。

所以也就分为两种情况:

Java程序是主语言,调用C/C++ 程序,这种方式就是Java使用动态链接库。

C/C++ 是主语言,调用Java程序,也就是C/C++ 直接创建JVM,将JVM作为一个盒子使用。

混合编程涉及的问题

1、参数传递问题,语言交互的基础是数据结构,怎么传递?

2、数据转换问题,不同语言的数据类型是不同的,如何转换?

3、线程问题,不同语言的线程绑定问题,

4、语言特性的对接,也就是jni 的一些接口

5、内存管理问题

如果你解决了上述的问题,基本上也没什么大问题了,啊哈哈,都是废话。

来个例子吧

创建Java项目

根据自己的习惯,直接创建一个你常用的java项目都行,不管是控制台项目还是web项目,只要能运行起来就可以

这里就写一个简单的计算加法的函数

package org.pdool;
 
/**
 * 动态库接口
 * @author xin.chong
 */
public class Lib {
    static {
//        String path = Lib.class.getClassLoader().getResource("").getPath();
//        System.loadLibrary("libjniDll");
        System.load("D:\\clion\\jniDll\\cmake-build-debug-visual-studio\\jniDll.dll");
    }
 
    /**
     * 动态库的函数接口
     * @param a
     * @param b
     * @return
     */
    public static native int sum(int a,int b);
}

注: 一般是Java侧定义好函数的签名,然后c++ 侧 再创建对应的函数。

搞个动态链接库

因为这是第一篇,估计进来看的你也是Java 程序,所以这一片也就难为你,直接给个动态链接库吧

因为文章中没办法增加附件,所以我上传到csdn 了,直接下载吧。

相信动态链接库你应该知道是什么,可以理解为java的第三方jar包,在运行的时候可以引用

当然这个定义不是很准确,但是概念上差不多,暂时这么理解吧

动态链接库和静态链接库

动态链接库 可以等价理解为jar包,编译好的class文件,任何一个程序都可以加载使用

静态链接库 可以理解为源码包,需要加载到项目中,自己进行编译,可以理解为java源文件

看下C++的代码

头文件.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class org_pdool_Lib */
 
#ifndef JNIDLL_LIBRARY_H
#define JNIDLL_LIBRARY_H
 
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     org_pdool_Lib
 * Method:    sum
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_org_pdool_Lib_sum
        (JNIEnv *, jclass, jint, jint);
 
#ifdef __cplusplus
}
#endif
#endif
cpp 文件

#include "library.h"
 
#include <iostream>
 
JNIEXPORT jint JNICALL Java_org_pdool_Lib_sum
        (JNIEnv * env, jclass j_class, jint a, jint b){
    return a +b;
}

测试运行起来

简单的写个测试代码

package org.pdool;
 
/**
 * Hello world!
 *
 */
public class App 
{
    public static void main(String[] args) {
        int result = Lib.sum(1,3);
        System.out.print("恭喜,JNI 第一个程序成功 ,the  result is  "+ result);
    }
}

注意点

注意我上面代码中的包名,因为我给的动态库中的方法签名是 因为我电脑是64位的,所以编译的dll 是64 位的,如果你不是,估计运行不起来,我没有测试 System.load 需要全路径,System.loadLibray() 会有搜索路径。 完整项目路径 :JNI工程完整例子,下载可运行-Java文档类资源-CSDN下载


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。