java - 我必须使用哪些类和方法才能从 C++ 调用 Java?

标签 java android c++ djinni

我目前正在使用 Djinni 并希望从 C++ 调用 Java 方法。

我有如下接口(interface)描述文件:

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

它生成这些文件:

  • src/main/cpp/ExampleSO.hpp : C++ ExampleSO包含虚拟析构函数和虚拟 PerformAddition 的类方法。
  • src/main/java/com/name/group/ExampleSO.java : Java ExampleSO包含 public abstract PerformAddition 的抽象类方法。
  • src/main/jni/NativeExampleSO.hpp/.cpp : JNI 绑定(bind)。

我想做的是创建一个新的 Java 类来扩展 ExampleSO Java 类(在接口(interface)描述中用 +j 指定),并能够从 C++ 文件中调用这些方法。

我可以在 JNI 绑定(bind)中看到有一个公共(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 接口(interface)的对象需要首先创建一个对象,这只能在实现该对象的语言中完成。一旦你得到了一个对象,你就可以在不同语言之间传递它,并从任何语言中自由地调用它。问题是你如何“引导”来获得你需要的对象。通常,引导总是必须从 Java/ObjC 开始。

Djinni 不支持直接使用构造函数,但支持单向静态方法(Java/ObjC -> C++)。您可以从 Java 进行调用以提供对象供 C++ 稍后存储和使用,或者您可以相反并使用静态方法作为工厂,让 Java 请求 C++ 创建对象。 如果您不介意使用全局状态,或者您需要立即使用该对象,则前者更简单。

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

在 Djinni 中有一个例子 test suite ,其中 test_helper 是一个带有方法 check_client_interface_ascii 的接口(interface)从 Java 中调用 here . Java 将 Java 对象作为参数传递,然后 C++ 对其进行调用。

如果你想避免使用全局状态,你可以只添加一个额外的步骤,Java 首先调用一个静态工厂方法来创建某种 C++“管理器”对象,然后对该对象进行调用以传递 example_so用于回调。具体如何发生可能取决于您应用的初始化需求。

关于java - 我必须使用哪些类和方法才能从 C++ 调用 Java?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46907806/

相关文章:

c++ - 计算三角形网格中的法线

c++ - 将 C++ 类放在另一个文件中 : compilation error

c++ - 使用对嵌入的双端队列成员的引用初始化的树元素会为此导致 nullptr

java - 禁止某人使用我的 java 程序的有效方法?

java - 如何在 Java 应用程序中使用 Jquery 评分星级?

java - 如何创建特定对象变量的子列表?

android - Android 是否在内部使用 Skia 在位图上绘制文本?

java - 如何在 streamex 中对映射流的 double 值求和?

android - 收到错误“无法从平台加载 PlatformApi;尝试使用cordova转换 Angular 应用程序时

java - 为 Android Studio 启用硬件加速