GCC中的外部“Java”块

时间:2013-03-01 22:22:29

标签: java c++ gcc java-native-interface gcj

我在C ++的GCC文档中找到了一个有趣的feature

  

java_interface

     

此类型属性通知C ++该类是Java接口。它可能仅适用于在 extern“Java”块中声明的类。将使用GCJ的接口表机制调度对此接口中声明的方法的调用,而不是常规的虚拟表调度。

据我了解,它看起来像这样:

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

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

2 个答案:

答案 0 :(得分:5)

GCJ为Java提供两个本机接口:JNI使用C和CNI使用C ++。由于您引用的示例使用类,因此必须引用后者。 CNI documentation on interfaces仅描述了如何从C ++代码访问Java中描述的接口。您的示例似乎是反过来的:用C ++编写的类,可以从Java访问并充当Java接口。

但是关于这一点的细节很少,因此试验和错误将是尝试这一点的一种方法,并且查看实际的GCC来源将是另一种。如果您想查看extern "Java"块和java_interface属性的一个示例,请查看java/lang/Readable.h。它包含Java接口java.lang.Readable的C ++表示。作为该文件的第一行,它是机器生成的。所以可能之所以文档这么少,是因为你不应该自己写这些东西。这只是GCJ如何实现CNI的细节。并且仔细查看上述文件,它们甚至违反了自己的文档,因为Readable.h具有extern块之外的属性,与您引用的代码段相反。

答案 1 :(得分:0)

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

extern "Java"
{
// some java definition
}

用于向GCC指定此块是java接口。它用于描述用于定义类的哪种类型的修改。名称mangling由gcc用于通过参数等生成函数名称...更多信息:http://www.agner.org/optimize/calling_conventions.pdf 因此,当您使用它导入Java代码时使用extern "Java",您可以将其称为juste,就像C / C ++中的任何函数一样,而不指定损坏的名称。我唯一使用它的是一个带有一些C函数的dll,用C ++代码加载,所以我使用extern“C”来指定GCC,这个函数的定义不使用名称修改。 那么,现在如何在java中调用本机方法,因为java中的所有方法都是方法,都是对象,没有函数。首先,您必须在java中描述您的类,您希望在本机语言中执行的所有函数都必须定义为本机:private native void print();例如。其次,在您的本机代码头中,您必须按照命名法定义方法:

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

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

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

现在,您可以使用Java创建Printer对象,并将print方法定义为native。 我希望我回答你的问题。