在 GCC 中执行“Java”块

2022-09-02 02:02:01

我在GCC文档中发现了一个有趣的功能,C++:

java_interface

此 type 属性通知C++该类是 Java 接口。它只能应用于在外部“Java”块中声明的类。对此接口中声明的方法的调用将使用GCJ的接口表机制进行调度,而不是常规的虚拟表调度。

据我所知,它看起来像这样:

extern "Java" {
    class NativeClass __attribute__((java_interface)) {
        //Implementation on native methods goes here.
    }
}

有人知道这方面的细节吗?如何从Java调用NativeClass的方法?也许有人在真正的现场尝试过?


答案 1

GCJ 为 Java 提供了两个本机接口:使用 C 的 JNI 和使用C++的 CNI。由于您引用的示例使用类,因此它必须引用后者。关于接口的 CNI 文档仅描述了如何从C++代码访问 Java 中描述的接口。您的示例似乎以相反的方式工作:一个用C++编写的类,可以从Java访问并用作Java接口。

但是关于这方面的细节很少,所以试错将是实验的一种方式,而查看实际的GCC来源将是另一种方式。如果你想看到块和属性的一个示例,看看java/lang/Readable.h。它包含 Java 接口 java.lang.Readable C++表示形式。正如该文件的第一行所述,它是计算机生成的。因此,文档如此之少的原因可能是因为您不应该自己编写这些东西。这只是GCJ如何实现CNI的细节。更仔细地查看上面的文件,似乎他们甚至违反了自己的文档,因为它具有块外部的属性,与您引用的片段相反。extern "Java"java_interfaceReadable.hextern


答案 2

我第一次遇到这种块类型时,它不是“java”,而是“C”,所以我认为这是同样的兴趣。由以下人员定义的块:

extern "Java"
{
// some java definition
}

用于向 GCC 指定此块是 Java 接口。它用于描述用于定义类的修改类型。gcc使用名称重整来按参数生成函数名称,等等...更多信息在这里 : http://www.agner.org/optimize/calling_conventions.pdf 所以你使用一个当你导入java代码时,你可以像C / C++中的任何函数一样调用它,而无需指定残缺的名称。我唯一使用它是一个dll,其中定义了一些C函数,加载到C++代码中,所以我使用extern“C”来向GCC指定此函数的定义不使用名称重整。好吧,现在如何在java中调用本机方法,因为Java中的所有内容都是方法,所有内容都是对象,没有函数。首先,你必须用java描述你的类,你想在原生语言中做的所有函数都必须被定义为原生的:为了example。其次,回到您的本机代码头,您必须按照命名法定义方法:extern "Java"private native void print();

extern "Java"
{
        JNIEXPORT YourReturnType JNICALL Java_ClassName_MethodName (JNIEnv* env, jobject obj);
}

至少,所有方法都必须看起来像这样,因为JNI将发送一个JNIEnv指针和一个对象,该方法中将是“this”,如果您有其他参数,则必须在2个基础之后给出它们。最后,您只需要在本机代码文件中实现所有方法,始终遵循规范,例如:

 JNIEXPORT void JNICALL Jave_Printer_print(JNIEnv* env, jobject obj)
 {
      printf("Hello world");
 }

现在,您可以在 Java 中创建一个 Printer 对象,并调用定义为本机的 print 方法。我希望我回答了你的问题。


推荐