从C ++调用Java必须使用什么类和方法? [英] What classes and methods do I have to use to call Java from C++?
问题描述
我目前正在与Djinni合作,并且想从C ++调用Java方法.
I'm currently working with Djinni and would like to call Java methods from C++.
我有以下接口描述文件:
I have the following interface description file:
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
:包含public abstract PerformAddition
方法的JavaExampleSO
抽象类. -
src/main/jni/NativeExampleSO.hpp
/.cpp
:JNI绑定.
src/main/cpp/ExampleSO.hpp
: C++ExampleSO
class containing a virtual destructor and a virtualPerformAddition
method.src/main/java/com/name/group/ExampleSO.java
: JavaExampleSO
abtract class containing apublic abstract PerformAddition
method.src/main/jni/NativeExampleSO.hpp
/.cpp
: JNI bindings.
我想做的是创建一个新的Java类,该类将扩展ExampleSO
Java类(如在接口说明中用+j
指定的那样),并能够从c ++文件中调用这些方法.
What I want to do is create a new Java class that will extend the ExampleSO
Java class (as specified in the interface description with +j
), and be able to call these methods from a c++ file.
我在JNI绑定中看到有一个公共的using CppType = std::shared_ptr<::ExampleSO>;
.给定名称,我假设这将是通过JNI桥调用Java方法的方式,但是当我尝试执行类似操作时,它会导致段错误:
I can see in the JNI bindings that there is a public using CppType = std::shared_ptr<::ExampleSO>;
. Given the name, I assumed that this would be the way to call Java methods through the JNI bridge, but it results in a segfault when I'm trying to do something like :
// 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
字段?
Do I have to initialize this neso
field in some way?
谢谢.
这是NativeExampleSO.hpp
(JNI桥)的内容,它可以使回答变得更容易:
Here is the content of NativeExampleSO.hpp
(JNI bridge), it could make answering easier :
// 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开始.
As you've noticed, using an object which implements a Djinni interface requires first creating an object, which can only be done in the language which implements the object. Once you've got an object you can pass it between languages, and make calls on it freely from any language. The question is how do you "bootstrap" to get the object you need. In general, bootstrapping always had to start from Java/ObjC.
Djinni不支持直接使用构造函数,而是在一个方向上支持静态方法(Java/ObjC-> C ++).您可以从Java调用以提供对象供C ++以后存储和使用,也可以相反,并将static方法用作工厂,让Java要求C ++创建对象. 如果您不介意使用全局状态,或者需要立即使用该对象,则前者会更简单.
Djinni doesn't support direct use of constructors, but supports static methods in one direction (Java/ObjC -> C++). You can either make a call from Java to provide the object for C++ to store and use later, or you can do the reverse and use the static method as a factory, letting Java ask C++ to create an object. The former is simpler if you don't mind using global state, or you need to use the object immediately.
interface example_so_setup +c {
set_example_so(obj: example_so)
}
Djinni中有一个示例测试套件,其中test_helper
是带有方法 check_client_interface_ascii
/djinni/test/ClientInterfaceTest.java#L15"rel =" nofollow noreferrer>此处. Java将Java对象作为参数传递,然后C ++对其进行调用.
There's an example in the Djinni test suite, where test_helper
is an interface with a method check_client_interface_ascii
which is called from Java here. Java passes aJava object as an argument, which C++ then makes calls on.
如果要避免使用全局状态,则可以添加一个额外的步骤,在该步骤中,Java首先调用静态工厂方法来创建某种C ++管理器".对象,然后对该对象进行调用以将example_so传递给回调.发生这种情况的具体细节可能取决于应用程序的初始化需求.
If you want to avoid using global state, you can just add an extra step, where Java first calls a static factory method to create some sort of C++ "manager" object, then makes a call on that object to pass the example_so for callbacks. The specifics of how that would happen probably depend on your app's initialization needs.
这篇关于从C ++调用Java必须使用什么类和方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!