extern «Java» блок в GCC

Я нашел интересный особенность в документации GCC для C ++:

java_interface

Этот атрибут типа сообщает C ++, что класс является интерфейсом Java. Он может применяться только к классам, объявленным в Экстерн «Ява» блок. Вызовы методов, объявленные в этом интерфейсе, будут отправляться с использованием механизма таблицы интерфейса GCJ вместо обычной отправки виртуальных таблиц.

Как я понимаю, это будет выглядеть примерно так:

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

Кто-нибудь знает подробности об этом? Как называть методы NativeClass с Java? Может быть, кто-нибудь пробовал это в реальной жизни?

22

Решение

GCJ предоставляет два родные интерфейсы для Java: JNI используя C и CNI используя C ++. Поскольку пример, который вы цитируете, использует класс, он должен ссылаться на последний. CNI документация по интерфейсам только описывает, как получить доступ к интерфейсам, описанным в Java из кода C ++. Ваш пример работает наоборот: класс, написанный на C ++, который доступен из Java и служит интерфейсом Java.

Но подробностей об этом доступно довольно мало, поэтому метод проб и ошибок будет одним из способов поэкспериментировать с этим, а другой взгляд — на источники GCC. Если вы хотите увидеть один пример обоих extern "Java" блок и java_interface атрибут, посмотрите на java/lang/Readable.h. Он содержит C ++ представление интерфейса Java java.lang.Readable. Как указано в первой строке этого файла, он генерируется машиной. Так что, вероятно, причина, по которой так мало документации, заключается в том, что вы не должны писать этот материал самостоятельно. Это просто деталь того, как GCJ реализует CNI. И если присмотреться более внимательно к приведенному выше файлу, кажется, что они даже нарушают собственную документацию, поскольку Readable.h имеет атрибут вне extern блок, в отличие от фрагмента, который вы цитировали.

5

Другие решения

Когда я впервые встретил этот тип блока, он был не для «java», а для «C», так что я думаю, что это тот же интерес. Блок определяется:

extern "Java"{
// some java definition
}

используется для указания GCC, что этот блок является интерфейсом Java. Используется для описания того, какой тип искажения используется для определения класса. Перенос имени используется gcc для генерации имени функции по параметрам и т. Д. Более подробная информация здесь: http://www.agner.org/optimize/calling_conventions.pdf
Таким образом, вы используете extern "Java" когда вы импортируете java-код с его помощью, вы можете назвать его juste как любую функцию в C / C ++ без указания искаженного имени. Я использовал его только для DLL с определенными в нем функциями C, загруженными в код на 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 и объект, который будет «this» в методе, если у вас есть другие аргументы, они должны быть заданы после 2 основ. Наконец, вам просто нужно реализовать все методы в файле с собственным кодом, всегда следуя норме, например:

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

Теперь вы можете создать объект Printer в Java и вызвать метод print, определенный как native.
Я надеюсь, что ответил на ваш вопрос.

0

По вопросам рекламы [email protected]