Подтвердить что ты не робот

Extern "Java" блок в GCC

Я нашел интересную в документации GCC для С++:

java_interface

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

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

extern "Java"
{
// some java definition
}

используется для указания GCC, что этот блок является интерфейсом java. Он используется для описания того типа манипуляции, который используется для определения класса. Название mangling используется gcc для генерации имени функции по параметрам и т.д. Подробнее здесь: http://www.agner.org/optimize/calling_conventions.pdf Таким образом, вы используете extern "Java", когда вы импортируете Java-код с ним, вы можете называть его juste, как любая функция в C/С++, без указания искаженного имени. Мое единственное использование этого было для dll с некоторыми функциями C, определенными в, загруженными в код на С++, поэтому я использую extern "C" для указания GCC, что определение этой функции не использует управление именами. Ну, теперь как вызвать собственный метод в java, потому что все в java - это метод, все это объект, функции нет. Во-первых, вы должны описать свой класс в java, все ваши функции, которые вы хотите сделать в native langage, должны быть определены как native: private native void print(); для примера. Во-вторых, вернитесь в свой собственный заголовок кода, вы должны определить метод, следующий за номенклатурой:

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

По крайней мере, весь метод должен выглядеть так, потому что JNI отправит указатель JNIEnv и объект, который будет "this" в методе, если у вас есть другие аргументы, они должны быть предоставлены после двух основ. Наконец, вам просто нужно реализовать весь метод в собственном файле кода, всегда следуя за нормой, например:

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

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