如何从本机C++用QT定义的功能(QJNienvironment ::登记符)

发布于 2025-02-01 21:05:21 字数 6323 浏览 5 评论 0原文

我正在使用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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

翻身的咸鱼 2025-02-08 21:05:21

Okey ...我读了本书的一部分: https://www.informit.com/store/java-native-interface-programers-guide-and-specification-9780201325775 并获取一些信息。

jstring Widget::cppNativeFunction(JNIEnv *env, jobject obj) {
        return (*env).NewStringUTF("Hello from C++/Qt!");
}
  • 是的。我终于在“ java:c ++/qt”的按钮上看到了!

Okey... I read part of this book: https://www.informit.com/store/java-native-interface-programmers-guide-and-specification-9780201325775 and get some info.

jstring Widget::cppNativeFunction(JNIEnv *env, jobject obj) {
        return (*env).NewStringUTF("Hello from C++/Qt!");
}
  • It's true. I finally see on my button "Java: Hello from C++/Qt!"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文