我必须使用哪些 类 和方法才能从 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
: C++ ExampleSO
class 包含虚拟析构函数和虚拟 PerformAddition
方法。
src/main/java/com/name/group/ExampleSO.java
: Java ExampleSO
抽象 class 包含一个 public abstract PerformAddition
方法。
src/main/jni/NativeExampleSO.hpp
/.cpp
: JNI 绑定。
我想做的是创建一个新的 Java class 来扩展 ExampleSO
Java class(如接口描述中指定+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 接口的对象需要首先创建一个对象,这只能在实现该对象的语言中完成。一旦你得到了一个对象,你就可以在不同语言之间传递它,并从任何语言中自由地调用它。问题是你如何“bootstrap”得到你需要的对象。一般来说,bootstrapping 总是要从 Java/ObjC.
开始
Djinni 不支持直接使用构造函数,但支持单向静态方法(Java/ObjC -> C++)。您可以从 Java 调用以提供对象供 C++ 存储和稍后使用,或者您可以相反并使用静态方法作为工厂,让 Java 要求 C++ 创建一个目的。
如果你不介意使用全局状态,或者你需要立即使用对象,前者更简单。
interface example_so_setup +c {
set_example_so(obj: example_so)
}
在 Djinni test suite, where test_helper
is an interface with a method check_client_interface_ascii
which is called from Java here 中有一个例子。 Java 传递一个Java 对象作为参数,然后 C++ 对其进行调用。
如果你想避免使用全局状态,你可以只添加一个额外的步骤,其中 Java 首先调用一个静态工厂方法来创建某种 C++“管理器”对象,然后调用该对象传递 example_so 进行回调。具体如何发生可能取决于您应用的初始化需求。
我目前正在使用 Djinni 并希望从 C++ 调用 Java 方法。
我有如下接口描述文件:
ExampleSO = interface +j {
PerformAddition(a: i32, b: i32): i32;
}
它生成这些文件:
src/main/cpp/ExampleSO.hpp
: C++ExampleSO
class 包含虚拟析构函数和虚拟PerformAddition
方法。src/main/java/com/name/group/ExampleSO.java
: JavaExampleSO
抽象 class 包含一个public abstract PerformAddition
方法。src/main/jni/NativeExampleSO.hpp
/.cpp
: JNI 绑定。
我想做的是创建一个新的 Java class 来扩展 ExampleSO
Java class(如接口描述中指定+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 接口的对象需要首先创建一个对象,这只能在实现该对象的语言中完成。一旦你得到了一个对象,你就可以在不同语言之间传递它,并从任何语言中自由地调用它。问题是你如何“bootstrap”得到你需要的对象。一般来说,bootstrapping 总是要从 Java/ObjC.
开始Djinni 不支持直接使用构造函数,但支持单向静态方法(Java/ObjC -> C++)。您可以从 Java 调用以提供对象供 C++ 存储和稍后使用,或者您可以相反并使用静态方法作为工厂,让 Java 要求 C++ 创建一个目的。 如果你不介意使用全局状态,或者你需要立即使用对象,前者更简单。
interface example_so_setup +c {
set_example_so(obj: example_so)
}
在 Djinni test suite, where test_helper
is an interface with a method check_client_interface_ascii
which is called from Java here 中有一个例子。 Java 传递一个Java 对象作为参数,然后 C++ 对其进行调用。
如果你想避免使用全局状态,你可以只添加一个额外的步骤,其中 Java 首先调用一个静态工厂方法来创建某种 C++“管理器”对象,然后调用该对象传递 example_so 进行回调。具体如何发生可能取决于您应用的初始化需求。