之前有写过c++调用c++的dll
https://blog.csdn.net/mandiheyanyu/article/details/120411187
这个里边虽然也涉及了java对dll的调用,但是因为当初写这个的时候,代码是别人直接拿给我的,我只要编译就行了,这篇这里是完整过程。
正确安装visual studio、eclipse、jdk。
我用的是eclipse,项目名什么的都是随便起的(命名十分不规范,已经被吐槽过了)。包名叫nist,类名叫NistDll,先声明好函数的名称、参数、返回值类型。
从本地文件中找到这个.java文件的位置,进入cmd运行指令。
java文件路径:E:\Java\workspace\test\src\nist
java上一级路径:E:\Java\workspace\test\src
包名:nist
类名:NistDll
指令为:javah -classpath java上一级路径 包名.类名
然后就会在本地见到一个.h文件
里边大约是这个样子的
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class nist_NistDll */
#ifndef _Included_nist_NistDll
#define _Included_nist_NistDll
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: nist_NistDll
* Method: java_nist_cs_segment_option_all
* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_nist_NistDll_java_1nist_1cs_1segment_1option_1all
(JNIEnv *, jobject, jstring, jstring, jstring);
/*
* Class: nist_NistDll
* Method: java_random_cs_segment_option
* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_nist_NistDll_java_1random_1cs_1segment_1option
(JNIEnv *, jobject, jstring, jstring, jstring);
#ifdef __cplusplus
}
#endif
#endif
再找到jdk的安装路径,include文件下的jni.h和include/win32下的jni_md.h,一起拷贝到c++的项目代码存放文件中。
项目右键单击添加现有项。
可以在属性→C/C++→预编译头文件,那里去掉pch.h可以不用预编译头;
也可以在pch.h文件里粘入java生成的.h头文件;
反正这块儿的操作灵活多样,因为起决定性作用的主要函数名。
.h文件中第一行的
#include <jni.h>
改为
#include 'jni.h'
要不然会报错找不到源文件,一般尖括号是用的库文件,单引号是用的自己写的头文件。
这里一定要调为x64,因为jdk如果想使用dll,两者的位数必须保持一致,jdk现在应该都是用的64位的吧?
随便写了一点用来做示范的代码
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <iostream>
using namespace std;
JNIEXPORT jint JNICALL Java_nist_NistDll_java_1nist_1cs_1segment_1option_1all
(JNIEnv *env, jobject object, jstring ss1, jstring ss2, jstring ss3)
{
string s1 = env->GetStringUTFChars(ss1, 0);
char str[256];
strcpy(str, s1.c_str());
string s2 = env->GetStringUTFChars(ss2, 0);
string s3 = env->GetStringUTFChars(ss3, 0);
printf("%s\n", str);
cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
return 0;
}
注意不能string转成char*,会在java调用的时候出现报错,具体看这里:
java调用c++编译的dll报错
https://blog.csdn.net/mandiheyanyu/article/details/124729858
看这个函数名里的nist_NistDll其实就是我java的那个包名和类名,如果没有生成.h文件,但是知道函数会在什么位置用,直接改函数名也不是不可以。
如果想要同一个dll,java也能用,c++也能用,就需要再写一个给c++的函数。也就是说,只是为了c++使用所生成的dll动态链接库,java是无法使用的。
项目右键单击生成。
在该项目的x64路径下会有个dll生成,把这个dll粘贴到java代码的地方,或者是粘到jdk存储路径的bin文件下都可以,但是后者要保证这个jdk/bin的路径写在了系统环境路径里。
再在java里进行dll的调用,我这里用的dll名字为nist.dll,写代码的时候只写.前面的名称。好像不同的编译器在引入dll的语句上略有差异,具体情况看自己到底用的是什么。