我想在Qt中创建一个.dll,并在Eclipse中的Java项目中使用生成的.dll。
我已经按照this教程创建了有效的dll。
有效的完整代码如下:
jniProjectExample_JniExample.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class jniProjectExample_JniExample */
#ifndef _Included_jniProjectExample_JniExample
#define _Included_jniProjectExample_JniExample
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: jniProjectExample_JniExample
* Method: callJavaMethod
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_jniProjectExample_JniExample_callJavaMethod
(JNIEnv *, jobject);
/*
* Class: jniProjectExample_JniExample
* Method: createAndReturnBean
* Signature: ()LjniProjectExample/Bean;
*/
JNIEXPORT jobject JNICALL Java_jniProjectExample_JniExample_createAndReturnBean
(JNIEnv *, jobject);
/*
* Class: jniProjectExample_JniExample
* Method: modifyBean
* Signature: (LjniProjectExample/Bean;)V
*/
JNIEXPORT void JNICALL Java_jniProjectExample_JniExample_modifyBean
(JNIEnv *, jobject, jobject);
/*
* Class: jniProjectExample_JniExample
* Method: crashTheJvm
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_jniProjectExample_JniExample_crashTheJvm
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
jniProjectExample_JniExample.cpp
#include "jniProjectExample_JniExample.h"
/* ------------------------------- A PROBLEM
#include <iostream>
#include <cstring>
*/
JNIEXPORT void JNICALL Java_jniProjectExample_JniExample_callJavaMethod (JNIEnv * env, jobject obj) {
jclass jniExampleCls = env->GetObjectClass(obj);
jmethodID mid = env->GetMethodID(jniExampleCls, "printSomething", "()V");
env->CallVoidMethod(obj, mid);
}
JNIEXPORT jobject JNICALL Java_jniProjectExample_JniExample_createAndReturnBean (JNIEnv *env, jobject obj) {
jclass beanClass = env->FindClass("jniProjectExample/Bean");
jmethodID constructorMethodId = env->GetMethodID(beanClass, "<init>", "()V");
jobject bean = env->NewObject(beanClass, constructorMethodId);
jstring newString = env->NewStringUTF("this bean has been created in Java_jniProjectExample_JniExample_createAndReturnBean");
jmethodID setStringMid = env->GetMethodID(beanClass, "setDataString", "(Ljava/lang/String;)V");
env->CallVoidMethod(bean, setStringMid, newString );
return bean;
}
JNIEXPORT void JNICALL Java_jniProjectExample_JniExample_modifyBean (JNIEnv *env, jobject obj, jobject bean) {
jclass beanCls = env->GetObjectClass(bean);
jmethodID setStringMid = env->GetMethodID(beanCls, "setDataString", "(Ljava/lang/String;)V");
// set the bean member "dataString"
jstring newString = env->NewStringUTF("world");
env->CallVoidMethod(bean, setStringMid, newString );
// set the bean member "dataByteArray"
jbyteArray newByteArray = env->NewByteArray(5);
jbyte buffer[5] = {5,4,3,2,1};
env->SetByteArrayRegion( newByteArray, 0, 5, buffer);
jmethodID setByteArrayMid = env->GetMethodID(beanCls, "setDataByteArray", "([B)V");
env->CallVoidMethod(bean, setByteArrayMid, newByteArray );
/* ----------------------- A PROBLEM
char bla[] = "something";
if(strcmp(bla, "label") == 0){
std::cout<<"strcmp 1";
}
else {
std::cout<<"strcmp 2";
} ------------------------ */
}
JNIEXPORT void JNICALL Java_jniProjectExample_JniExample_crashTheJvm (JNIEnv *env, jobject obj) {
//stack overflow - http://en.wikipedia.org/wiki/Stack_overflow
double x[1000000];
}
jniExampleLibrary.pro
#-------------------------------------------------
#
# Project created by QtCreator 2019-03-23T09:43:24
#
#-------------------------------------------------
QT -= core gui
TARGET = jniExampleLibrary
TEMPLATE = lib
DEFINES += JNIEXAMPLELIBRARY_LIBRARY
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
QMAKE_CFLAGS += -std=c++11
macx:INCLUDEPATH += /Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/include \
/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/include/darwin
win32:INCLUDEPATH += "C:\Program Files\Java\jdk1.8.0_181\include" \
"C:\Program Files\Java\jdk1.8.0_181\include\win32"
SOURCES += \
jniProjectExample_JniExample.cpp
HEADERS += \
jni.h \
jni_md.h \
jniProjectExample_JniExample.h
unix {
target.path = /usr/lib
INSTALLS += target
}
Bean.java
package jniProjectExample;
public class Bean {
//public members
public String dataString;
public byte[] dataByteArray;
public Bean() {}
//getters and setters
public String getDataString() {
return dataString;
}
public void setDataString(String dataString) {
this.dataString = dataString;
}
public byte[] getDataByteArray() {
return dataByteArray;
}
public void setDataByteArray(byte[] dataByteArray) {
this.dataByteArray = dataByteArray;
}
@Override
public String toString(){
String ret = "string = " + dataString;
ret += " / byteArray =";
if ( dataByteArray != null ) {
for ( byte b : dataByteArray) {
ret += " " + b;
}
}
return ret;
}
}
JniExample.java
package jniProjectExample;
public class JniExample {
static {
System.loadLibrary("jniExampleLibrary");
}
// native methods
/**
* this method calls printSomething
*/
public native void callJavaMethod();
/**
* this method creates an instance of Bean and returns it
*/
public native Bean createAndReturnBean();
/**
* this method takes an instance of Bean as parameter and changes the value
* of its members
*/
public native void modifyBean(Bean bean);
/**
* this method will the JVM when invoked
*/
public native void crashTheJvm();
public void printSomething() {
System.out.println("Thanks for watching this video");
}
public void runExample1() {
System.out.println("starting runExample1...");
callJavaMethod();
}
public void runExample2() {
System.out.println("starting runExample2...");
Bean bean = createAndReturnBean();
System.out.println("returned= " + bean.toString());
}
public void runExample3() {
System.out.println("starting runExample3...");
Bean bean = new Bean();
bean.setDataString("hello");
byte[] byteArray = new byte[] { 0x01, 0x02, 0x03 };
bean.setDataByteArray(byteArray);
System.out.println("before: " + bean.toString());
modifyBean(bean);
System.out.println("after: " + bean.toString());
}
public void runExample4() {
System.out.println("starting runExample4...");
crashTheJvm();
}
}
Main.java
package jniProjectExample;
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("Starting JavaMain...");
System.out.println(System.getProperty("java.library.path"));
JniExample jniExample = new JniExample();
jniExample.runExample1();
jniExample.runExample2();
jniExample.runExample3();
// jniExample.runExample4();
}
}
只要dll不包含任何标准的c ++函数,就可以在Java中调用dll。一旦我在jniProjectExample_JniExample.cpp中取消注释此代码,就会出现问题,并且Java应用程序会引发异常,说dll“不是有效的Win32应用程序”。
我在Windows 10上,使用MinGW 64位编译器生成dll。显然,这种标准库链接在运行时存在一些问题,但是我似乎无法一整天都解决这个问题,因此,感谢您的帮助。