从C ++调用Java必须使用什么类和方法? [英] What classes and methods do I have to use to call Java from C++?

查看:125
本文介绍了从C ++调用Java必须使用什么类和方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在与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方法的Java ExampleSO抽象类.
  • src/main/jni/NativeExampleSO.hpp/.cpp:JNI绑定.
  • src/main/cpp/ExampleSO.hpp: C++ ExampleSO class containing a virtual destructor and a virtual PerformAddition method.
  • src/main/java/com/name/group/ExampleSO.java: Java ExampleSO abtract class containing a public 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆