C++ 通过jni生成库供JAVA调用(下)--C++生成库并JAVA可以调用(windows)

C++ 通过jni生成库供JAVA调用(下)–C++生成库并JAVA可以调用(windows)

项目上 JAVA通过C++库去调用硬件设备,需要用C++封装库,然后JAVA调用C++的库,这里描述JAVA调用C++库的过程。
这里实现C++生成库可让JAVA通过JNI去调用

编译环境:VS2015; eclipse/(使用命令行也操作可行,eclipse不熟悉,然后开始没有使用它)
语言: C++, JAVA
这个过程中遇到了一些坑,JAVA也是只会写个hello world ,然后在java调用库的时候会出现一些问题。

使用notepad++建立个.java文件,输出所需要实现的一些接口

使用文本来实现.java文件

在java文件里面声明在C++里面需要实现的接口或者已经存在的接口,数据类型需要适当的转换。

在D:\jni\java_jni\java_jni下建立个文件jniCppSDK.java
并输入一下内容

package java_jni;

public class jniCppSDK {
    public native void sayHello();
    public native int sum(int a, int b);
    public native int max(int a, int b, int c);
    static
    {
        System.loadLibrary("jniCppSDK");        
    }
    public static void main(String[] args)
    {
        jniCppSDK test = new jniCppSDK();

        test.sayHello();
        System.out.println(test.sum(10, 21));
        System.out.println(test.max(10, 12, 20));

        System.out.println("hello JAVA");
    }
}

或者使用eclipse来实现.java文件

该步骤和上个步骤的目的是一样的

  • 打开eclipse – File – New – Java Project( 保存路径为 D:\jni\java_jni\java_jni_eclipse,工程名称:java_jni_eclipse) – Next – Finish
  • 在src处右键 New – Package ,Name 更改为java_jni
  • 在java_jni包处右键 New – Class , Class名字设置为jniCppSDK

在jniCppSDK.java文件里面可以看到内容:

package java_jni;

public class jniCppSDK {

}

将之前代码添加到该Class里面

package java_jni;

public class jniCppSDK {
    public native void sayHello();
    public native int sum(int a, int b);
    public native int max(int a, int b, int c);
    static
    {
        System.loadLibrary("jniCppSDK");        
    }
    public static void main(String[] args)
    {
        jniCppSDK test = new jniCppSDK();

        test.sayHello();
        System.out.println(test.sum(10, 21));
        System.out.println(test.max(10, 12, 20));

        System.out.println("hello JAVA");
    }
}

利用javah 生成jni头文件

C++代码实现头文件这些接口,然后可以生成JAVA可以调用的库了

对使用notepad++之类的文本编辑器,进行操作
  • 在jniCppSDK .java文件路径下,按住shift键+鼠标右键,点击在此处打开Powershell窗口,输出 javac jniCppSDK.java,可以看到文件夹里面多出了jniCppSDK.class文件
  • 由于.java文件使用package java_jni;声明,需要在java文件的父路径上进行操作,在shell里面输出cd ../, 路径会回到 D:\jni\java_jni里面,然后输入javah java_jni.jniCppSDK,来生成jni头文件,然后会在该路径下出现java_jni_jniCppSDK.h文件

如果java文件里面没有package的声明的话,直接在java文件所在路径下javah java_jni.jniCppSDK就可以了,因为java文件里面有package java_jni;所以在生成头文件的时候需要在java文件的上层目录下进行操作

对使用eclipse的java文件操作
  • 进入到eclipse工程里面,到D:\jni\java_jni\java_jni_eclipse\src\java_jni路径下,然后进入Powershell路径下’javac jniCppSDK.java’
  • 然后cd ../,到上级目录下,运行javah java_jni.jniCppSDK,然后该路径下会出现
    java_jni_jniCppSDK.h文件,

上面两种情况下生成 jni头文件,比较两种状况下得到的jni头文件,两者完全一样。

通过jni头文件和C++里面的程序进行对接

VS工程环境搭建

  • D:\jni\java_jni里面,创建win32控制台的工程,工程名称为jniCppSDK,程序类型选择DLL,空项目。
  • java_jni_jniCppSDK.h头文件添加到工程头文件里面,将testSDK.cpp工程源文件(可以自己新建个源文件)
// testSDK.cpp : 定义 DLL 应用程序的导出函数。
//
#include <iostream>
#include "java_jni_jniCppSDK.h"

void helloSDK()
{
    std::cout << "hello sdk" << std::endl;
}
int mySum(int a, int b)
{
    return (a + b);
}
int myMax(int a, int b, int c)
{
    int max = a;

    if (max < b)
        max = b;
    if (max < c)
        max = c;

    return max;
}
  • 此时编译的话,会出现无法打开 源 文件 “jni.h”的情况,需要将java的jni路径添加到附加包含目录配置属性C/C++附加包含目录 添加C:\Program Files\Java\jdk1.8.0_144\include\;C:\Program Files\Java\jdk1.8.0_144\include\win32,

    注意:x86平台和x64平台的设置,可能是目录添加到x86里面,缺以x64平台运行的,所有还是会找不到jni.h文件,所以我两个平台都添加了附加包含目录。

  • 添加Source.def文件,输入以下内容,否则的话,链接不到方法。

LIBRARY "jniCppSDK"  
EXPORTS
    Java_java_1jni_jniCppSDK_sayHello @1
    Java_java_1jni_jniCppSDK_sum @2
    Java_java_1jni_jniCppSDK_max @3

编写代码

testSDK.cpp与生成的jni头文件接口对接,完成之后的代码:

// testSDK.cpp : 定义 DLL 应用程序的导出函数。
//
#include <iostream>

#include "java_jni_jniCppSDK.h"


void helloSDK()
{
    std::cout << "hello sdk" << std::endl;
}
int mySum(int a, int b)
{
    return (a + b);
}
int myMax(int a, int b, int c)
{
    int max = a;

    if (max < b)
        max = b;
    if (max < c)
        max = c;

    return max;
}

/*
* Class:     java_jni_jniCppSDK
* Method:    sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_java_1jni_jniCppSDK_sayHello
(JNIEnv *, jobject)
{
    helloSDK();
}

/*
* Class:     java_jni_jniCppSDK
* Method:    sum
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_java_1jni_jniCppSDK_sum
(JNIEnv * env , jobject obj, jint a, jint b)
{
    return (jint)(mySum((int)a, (int)b));
}

/*
* Class:     java_jni_jniCppSDK
* Method:    max
* Signature: (III)I
*/
JNIEXPORT jint JNICALL Java_java_1jni_jniCppSDK_max
(JNIEnv * env, jobject obj, jint a, jint b, jint c)
{
    return (jint)(myMax((int)a, (int)b, (int)c));
}

编译运行,生成dll文件。

将dll文件放到D:\jni\java_jni路径下,命令行下运行java程序

D:\jni\java_jni> java java_jni.jniCppSDK
运行结果:

hello sdk
31
20
hello JAVA

将dll文件丢到eclipse工程路径下运行

运行结果:

hello sdk
31
20
hello JAVA

这里写图片描述

java调用C++库成功

附上测试源码:

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值