Вызовите метод Java - PullRequest
       10

Вызовите метод Java

4 голосов
/ 16 июня 2011

Сегодня я создал свой первый собственный вызов на Java с помощью Android SDK.
Я нашел несколько примеров, но они не соответствуют заголовку функции.

Я использовал всегда

JNIEXPORT void JNICALL Java_com_test_Calculator_calcFileSha1 
   (JNIEnv *, jclass, jstring);

но я видел

JNIEXPORT void JNICALL Java_com_test_Calculator_calcFileSha1 
   (JNIEnv *, jobject, jstring);

Принадлежность к головам отличается от того, чтобы получить класс вызывающего.
Но какой предпочтительный способ?

Из кода C ++ я хочу вызвать метод Java. Я нашел документацию JNI ( Методы вызова экземпляра ).
Но я не знаю, каким должен быть первый параметр (объект).

Я попытался дать экземпляр класса, который я получаю из вызова нативного метода, который завершается ошибкой AbstractMethodError.

Фиксированный исходный код:

public class TestCalc extends Activity {
   static {
      System.loadLibrary("Test");
   }

   private void setFilesize(long size) {

   }
}

Родная библиотека:

// header
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_com_test_TestCalc_calcFilesize
  (JNIEnv *, jobject, jstring);

  void setFilesize(const INT_64 size);

#ifdef __cplusplus
}
#endif

#endif

// code
JNIEnv * callEnv;
jobject callObj;


JNIEXPORT void JNICALL Java_com_test_SHA1Calc_calcFileSha1
  (JNIEnv * env, jobject jobj, jstring file)
{
    callEnv = env;
    callObj = jobj;

    [...]
}

  void setFilesize(const INT_64 size) {
      jmethodID mid;
      jclass cls;

      cls=callEnv->FindClass("com/test/TestCalc");    
      mid=callEnv->GetMethodID(cls, "setFilesize", "(J)V");
      if (mid == 0) {
        __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:LC: [%s]", "Cannot find method setFilesize");
        return;
      }

      callEnv->ExceptionClear();
      callEnv->CallVoidMethod(callObj, mid, size);
      if(callEnv->ExceptionOccurred()) {
        callEnv->ExceptionDescribe();
        callEnv->ExceptionClear();
      }
  }

Спасибо за любые советы.

Ответы [ 2 ]

2 голосов
/ 16 июня 2011

Вызовите [тип] Метод только для частных методов и конструкторов. ( Вызов методов экземпляра ) Когда вы вызываете открытый метод, вы получите AbstractMethodError .

0 голосов
/ 16 июня 2011

jobject может быть любым Java-объектом, в то время как jclass должен быть объектом, представляющим java.lang.Class. В C API jobject и jclass - это то же самое, в то время как C ++ API пытается обеспечить безопасность типов и объявляет их как различные типы, где jclass наследует jobject. Второй аргумент должен представлять класс, поэтому jclass предпочтительнее. Даже если в C это не имеет значения, это может дать подсказку разработчику или даже сэкономить ваше время, если вы когда-нибудь решите перейти на C ++. Подробнее о типах JNI здесь .

...