簡體   English   中英

我必須使用哪些類和方法從 C++ 調用 Java?

[英]What classes and methods do I have to use to call Java from C++?

我目前正在使用 Djinni 並想從 C++ 調用 Java 方法。

我有以下接口描述文件:

ExampleSO = interface +j {
  PerformAddition(a: i32, b: i32): i32;
}

它生成這些文件:

  • src/main/cpp/ExampleSO.hpp :包含虛擬析構函數和虛擬PerformAddition方法的 C++ ExampleSO類。
  • src/main/java/com/name/group/ExampleSO.java :包含public abstract PerformAddition方法的 Java ExampleSO抽象類。
  • src/main/jni/NativeExampleSO.hpp / .cpp :JNI 綁定。

我想要做的是創建一個新的 Java 類,它將擴展ExampleSO Java 類(如接口描述中指定的+j ),並且能夠從 C++ 文件調用這些方法。

我可以在 JNI 綁定中看到有一個 public using CppType = std::shared_ptr<::ExampleSO>; . 鑒於名稱,我認為這將是通過 JNI 橋調用 Java 方法的方式,但是當我嘗試執行以下操作時會導致段錯誤:

// SampleClass.hpp
#include "ExampleSO.hpp"

class SampleClass: ExampleSO {
private:
    NativeExampleSO::CppType neso;
public:
    int32_t PerformAddition(int32_t a, int32_t b) override;
}

// SampleClass.cpp
#include "SampleClass.hpp"

int32_t SampleClass::PerformAddition(int32_t a, int32_t b) {
    neso->PerformAddition(a, b); // Crash
}

我是否必須以某種方式初始化這個neso字段?

提前致謝。

編輯:這是NativeExampleSO.hpp (JNI 橋)的內容,它可以使回答更容易:

// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from ExampleSO.djinni

#pragma once

#include "ExampleSO.hpp"
#include "djinni_support.hpp"

namespace djinni_generated {

class NativeExampleSO final : ::djinni::JniInterface<::ExampleSO, NativeExampleSO> {
public:
    using CppType = std::shared_ptr<::ExampleSO>;
    using CppOptType = std::shared_ptr<::ExampleSO>;
    using JniType = jobject;

    using Boxed = NativeExampleSO;

    ~NativeExampleSO();

    static CppType toCpp(JNIEnv* jniEnv, JniType j) { return ::djinni::JniClass<NativeExampleSO>::get()._fromJava(jniEnv, j); }
    static ::djinni::LocalRef<JniType> fromCppOpt(JNIEnv* jniEnv, const CppOptType& c) { return {jniEnv, ::djinni::JniClass<NativeExampleSO>::get()._toJava(jniEnv, c)}; }
    static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c) { return fromCppOpt(jniEnv, c); }

private:
    NativeExampleSO();
    friend ::djinni::JniClass<NativeExampleSO>;
    friend ::djinni::JniInterface<::ExampleSO, NativeExampleSO>;

    class JavaProxy final : ::djinni::JavaProxyHandle<JavaProxy>, public ::ExampleSO
    {
    public:
        JavaProxy(JniType j);
        ~JavaProxy();

        int32_t PerformAddition(int32_t a, int32_t b) override;

    private:
        friend ::djinni::JniInterface<::ExampleSO, ::djinni_generated::NativeExampleSO>;
    };

    const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/name/group/ExampleSO") };
    const jmethodID method_PerformAddition { ::djinni::jniGetMethodID(clazz.get(), "PerformAddition", "(II)I") };
};

}  // namespace djinni_generated

正如您所注意到的,使用實現 Djinni 接口的對象需要首先創建一個對象,這只能在實現該對象的語言中完成。 一旦你有了一個對象,你就可以在語言之間傳遞它,並從任何語言自由地調用它。 問題是你如何“引導”來獲得你需要的對象。 一般來說,引導總是必須從 Java/ObjC 開始。

Djinni 不支持直接使用構造函數,但支持一個方向的靜態方法(Java/ObjC -> C++)。 您可以從 Java 調用以提供對象供 C++ 存儲和稍后使用,或者您可以反向操作並將靜態方法用作工廠,讓 Java 要求 C++ 創建一個對象。 如果您不介意使用全局狀態,或者您需要立即使用對象,則前者更簡單。

interface example_so_setup +c {
    set_example_so(obj: example_so)
}

有一個在Djinni一個例子測試套件,其中test_helper是一個方法的接口check_client_interface_ascii這是從Java稱為這里 Java 傳遞一個 Java 對象作為參數,然后 C++ 調用它。

如果您想避免使用全局狀態,您可以添加一個額外的步驟,其中 Java 首先調用靜態工廠方法來創建某種 C++“管理器”對象,然后對該對象進行調用以傳遞 example_so 以進行回調。 具體如何發生可能取決於您的應用程序的初始化需求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM