如何从本机C++用QT定义的功能(QJNienvironment ::登记符)
我正在使用QT6.2.4,并尝试从Java中的C ++获得答案。
Logic:
C++ calls Java method, who calls C++ Method.
C++ Method (Hello from C++/Qt)
Java Method (Java: + C++ Method)
and starter C++ Method set result on Button
My expectations:
"Java: Hello from C++/Qt",
But i see:
"Java: null"
My code:
https://github.com/dail45/JNItestw
(Sorry, i can't write code here. Editor raise warnings)
从控制台我知道: cppnativeFun真的运行(我从Java 0中看到Hello) 我做错了什么?如何从本地Fun(Java)获得结果? 我需要做什么,因为没有“ null”会得到“从C ++/QT”获得“ Hello from C ++/QT”?
PS 对不起设计和代码,内置编辑器不断抱怨我不正确地强调了代码。
UDP: ./jnitestw.pro = core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
widget.cpp
HEADERS += \
widget.h
FORMS += \
widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
OTHER_FILES += \
android/AndroidManifest.xml \
android/src/org/example/JNItest/MyJNI.java
./main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
./widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
auto activity = QJniObject(QNativeInterface::QAndroidApplication::context());
QJniObject MyJni = QJniObject("org/example/JNItest/MyJNI",
"(Landroid/app/Activity;)V",
activity.object<jobject>());
QJniEnvironment env;
jclass objectClass = env->GetObjectClass(MyJni.object<jobject>());
JNINativeMethod methods[] = {{"nativeFun", "()Ljava/lang/String;", reinterpret_cast<void*>(cppNativeFunction)}};
env->RegisterNatives(objectClass, methods, sizeof(methods) / sizeof(methods[0]));
env->DeleteLocalRef(objectClass);
layout->addWidget(btn);
btn->setText("click me");
btn->setStyleSheet("QPushButton {padding: 25px;}");
QObject::connect(btn, &QPushButton::clicked, this, [this]() {
auto activity = QJniObject(QNativeInterface::QAndroidApplication::context());
QJniObject MyJni = QJniObject("org/example/JNItest/MyJNI",
"(Landroid/app/Activity;)V",
activity.object<jobject>());
QJniObject res = MyJni.callObjectMethod("jniFun", "()Ljava/lang/String;").object<jobject>();
this->btn->setText(res.toString());
});
}
Widget::~Widget()
{
delete ui;
}
int counter = 0;
jstring Widget::cppNativeFunction(JNIEnv *env, jobject obj) {
qDebug() << "Hello from java!" << QString::number(counter++);
return QJniObject::fromString("Hello from C++/Qt!").object<jstring>();
}
./widget.h./android/src/org/org/example/jnitest/jnitest/myjni.java
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QJniObject>
#include <QJniEnvironment>
#include <jni.h>
#include <QPushButton>
#include <QDebug>
#include <QHBoxLayout>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
QHBoxLayout *layout = new QHBoxLayout(this);
QPushButton *btn = new QPushButton(this);
static jstring cppNativeFunction(JNIEnv *env, jobject obj);
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
qt +
package org.example.JNItest;
import android.app.Activity;
public class MyJNI
{
private final Activity m_MainActivity;
public MyJNI(final Activity MainActivity) {
m_MainActivity = MainActivity;
}
public native String nativeFun();
public String jniFun() {
String a = nativeFun();
System.out.println(a);
return "Java: " + a;
}
}
./android/android/androidmanifest.xml
<?xml version="1.0"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.example.JNItestw" android:installLocation="auto" android:versionCode="1" android:versionName="1.0">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:smallScreens="true"/>
<application android:name="org.qtproject.qt.android.bindings.QtApplication" android:extractNativeLibs="true" android:hardwareAccelerated="true" android:label="JNItestw" android:requestLegacyExternalStorage="true" android:allowNativeHeapPointerTagging="false">
<activity android:name="org.qtproject.qt.android.bindings.QtActivity" android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:label="JNItestw" android:launchMode="singleTop" android:screenOrientation="unspecified">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="JNItestw"/>
<meta-data android:name="android.app.arguments" android:value=""/>
<meta-data android:name="android.app.extract_android_style" android:value="minimal"/>
</activity>
</application>
<!-- %%INSERT_PERMISSIONS -->
<!-- %%INSERT_FEATURES -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
</manifest>
I'm using Qt6.2.4, and trying to get answer from C++ in Java.
Logic:
C++ calls Java method, who calls C++ Method.
C++ Method (Hello from C++/Qt)
Java Method (Java: + C++ Method)
and starter C++ Method set result on Button
My expectations:
"Java: Hello from C++/Qt",
But i see:
"Java: null"
My code:
https://github.com/dail45/JNItestw
(Sorry, i can't write code here. Editor raise warnings)
From console i know that:
cppNativeFun really running (I see Hello from Java 0)
What i did wrong? How to get result from nativeFun (Java)?
What i need do that get "Hello from C++/Qt" without "null"?
P.s.
Sorry for the design and code, the built-in editor constantly complains that I highlighted the code incorrectly.
Udp:
./JNItestw.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
widget.cpp
HEADERS += \
widget.h
FORMS += \
widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/${TARGET}/bin
else: unix:!android: target.path = /opt/${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
ANDROID_PACKAGE_SOURCE_DIR = $PWD/android
OTHER_FILES += \
android/AndroidManifest.xml \
android/src/org/example/JNItest/MyJNI.java
./main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
./widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
auto activity = QJniObject(QNativeInterface::QAndroidApplication::context());
QJniObject MyJni = QJniObject("org/example/JNItest/MyJNI",
"(Landroid/app/Activity;)V",
activity.object<jobject>());
QJniEnvironment env;
jclass objectClass = env->GetObjectClass(MyJni.object<jobject>());
JNINativeMethod methods[] = {{"nativeFun", "()Ljava/lang/String;", reinterpret_cast<void*>(cppNativeFunction)}};
env->RegisterNatives(objectClass, methods, sizeof(methods) / sizeof(methods[0]));
env->DeleteLocalRef(objectClass);
layout->addWidget(btn);
btn->setText("click me");
btn->setStyleSheet("QPushButton {padding: 25px;}");
QObject::connect(btn, &QPushButton::clicked, this, [this]() {
auto activity = QJniObject(QNativeInterface::QAndroidApplication::context());
QJniObject MyJni = QJniObject("org/example/JNItest/MyJNI",
"(Landroid/app/Activity;)V",
activity.object<jobject>());
QJniObject res = MyJni.callObjectMethod("jniFun", "()Ljava/lang/String;").object<jobject>();
this->btn->setText(res.toString());
});
}
Widget::~Widget()
{
delete ui;
}
int counter = 0;
jstring Widget::cppNativeFunction(JNIEnv *env, jobject obj) {
qDebug() << "Hello from java!" << QString::number(counter++);
return QJniObject::fromString("Hello from C++/Qt!").object<jstring>();
}
./widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QJniObject>
#include <QJniEnvironment>
#include <jni.h>
#include <QPushButton>
#include <QDebug>
#include <QHBoxLayout>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
QHBoxLayout *layout = new QHBoxLayout(this);
QPushButton *btn = new QPushButton(this);
static jstring cppNativeFunction(JNIEnv *env, jobject obj);
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
./android/src/org/example/JNItest/MyJNI.java
package org.example.JNItest;
import android.app.Activity;
public class MyJNI
{
private final Activity m_MainActivity;
public MyJNI(final Activity MainActivity) {
m_MainActivity = MainActivity;
}
public native String nativeFun();
public String jniFun() {
String a = nativeFun();
System.out.println(a);
return "Java: " + a;
}
}
./android/AndroidManifest.xml
<?xml version="1.0"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.example.JNItestw" android:installLocation="auto" android:versionCode="1" android:versionName="1.0">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:smallScreens="true"/>
<application android:name="org.qtproject.qt.android.bindings.QtApplication" android:extractNativeLibs="true" android:hardwareAccelerated="true" android:label="JNItestw" android:requestLegacyExternalStorage="true" android:allowNativeHeapPointerTagging="false">
<activity android:name="org.qtproject.qt.android.bindings.QtActivity" android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:label="JNItestw" android:launchMode="singleTop" android:screenOrientation="unspecified">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="JNItestw"/>
<meta-data android:name="android.app.arguments" android:value=""/>
<meta-data android:name="android.app.extract_android_style" android:value="minimal"/>
</activity>
</application>
<!-- %%INSERT_PERMISSIONS -->
<!-- %%INSERT_FEATURES -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
</manifest>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Okey ...我读了本书的一部分: https://www.informit.com/store/java-native-interface-programers-guide-and-specification-9780201325775 并获取一些信息。
Okey... I read part of this book: https://www.informit.com/store/java-native-interface-programmers-guide-and-specification-9780201325775 and get some info.