JNI Вызывает разные в C vs С++?
Итак, у меня есть следующий код в C, который использует Java Native Interface, но я хотел бы преобразовать его в С++, но не уверен, как это сделать.
#include <jni.h>
#include <stdio.h>
#include "InstanceMethodCall.h"
JNIEXPORT void JNICALL
Java_InstanceMethodCall_nativeMethod(JNIEnv *env, jobject obj)
{
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "()V");
if (mid == NULL) {
return; /* method not found */
}
printf("In C\n");
(*env)->CallVoidMethod(env, obj, mid);
}
Программа Java:
class InstanceMethodCall {
private native void nativeMethod();
private void callback() {
System.out.println("In Java");
}
public static void main(String args[]) {
InstanceMethodCall c = new InstanceMethodCall();
c.nativeMethod();
}
static {
System.loadLibrary("InstanceMethodCall");
}
}
В чем различия, с которыми JNI взаимодействует с C и С++? Любая помощь приветствуется.
Спасибо, Пит
Ответы
Ответ 1
Раньше у меня была книга Essential JNI. И хотя это отчасти датировано, многие из них все еще работают сегодня.
Если я правильно помню, в C конструкторы Java являются просто указателями. Таким образом, в вашем коде "(*env)->
" является указателем разыменования, чтобы предоставить вам доступ к основным методам.
Для С++ "env
" на самом деле является объектом - другой сущностью, чем C-указатель. (И JNI может фактически предоставлять реальные объекты для вашего кода на С++ для управления, поскольку С++ фактически поддерживает объекты.) Поэтому "env->
" имеет другое значение в С++, это означает "вызвать метод, содержащийся в объекте, на который указывает "env
".
Другим отличием, я считаю, является то, что многие из функций C-JNI требуют, чтобы одним из ваших параметров был "JNIEnv *env
". Итак, в C вам, возможно, придется сказать (*env)->foo(env, bar)
. С С++ вторая ссылка на "env
" не нужна, поэтому вы можете вместо этого сказать "env->foo(bar)
"
К сожалению, у меня нет вышеупомянутой книги передо мной, поэтому я не могу это подтвердить! Но я думаю, что исследование этих двух вещей (особенно их поиск в google или в другом коде JNI) доставит вам довольно далеко.
Ответ 2
Вы пробовали обернуть свой код C в extern "C"
. См. С++ Faq Lite для получения дополнительной информации и для других возможных механизмов, позволяющих использовать ваш C-код с С++.
Ответ 3
Основное различие между вызовами JNI в C и CPP заключается в следующем:
C-стиль JNI выглядит
(* env) → SomeJNICall (env, param1...)
Стиль С++ JNI выглядит так:
env- > SomeJNICall (param1...)
чтобы преобразовать его в CPP, вам нужно сделать
Java_InstanceMethodCall_nativeMethod(JNIEnv *env, jobject obj)
{
jclass cls = env->GetObjectClass(obj);
jmethodID mid = env->GetMethodID(cls, "callback", "()V");
if (mid == NULL) {
return; /* method not found */
}
printf("In C++\n");
env->CallVoidMethod(obj, mid);
//rest of your code
Кроме того, убедитесь, что ваши функции JNI соблюдают соглашение об именах.
Пример:
JNIEXPORT jint JNICALL Java_com_shark_JNITestLib_JNITestLib_startServer(JNIEnv* env, jobject o, jstring inputName, jstring streamName, jstring description) {
Вы можете видеть, что соглашение
Java_ (имя пакета) _ (имя_файла) _ (имя метода)
так как вышеприведенное было использовано в классе, таком как
package com.shark.JNITestLib
import java.util.stuff;
public class JNITestLib
{
static
{
System.loadLibrary("myJNIlib");
}
public native synchronized int startServer(String inputName, String streamName, String description);
//more class stuff...
}
При работе с JNI я сделал соглашение, чтобы назвать класс, содержащий вызовы JNI, тем же именем, что и пакет. Вот почему вы дважды видите JNITestLib (и поэтому мой JNI работает сразу с места в карьер, потому что я всегда забываю, как правильно назвать вызовы JNI)
Привет, надеюсь, я помог:)
Ответ 4
Прошло некоторое время с тех пор, как я коснулся стандартного С++, но я все равно попробую.
"(*env)->
" выглядит странно для меня. Разве это не должно быть "env->
"?
Возможно, я ошибаюсь, и это должно сработать, но зачем все это усложнять?
Ответ 5
Первый код - правильный С++, не так ли? Итак, все готово!
Серьезно, что вы хотите изменить в этом коде? Почему?