0

因此,我正在重新创建一个 Palm Pilot 程序以在 Android 中运行。有一个库我必须继续使用用 C 编写的,但我正在重写应用程序的 UI 组件和蓝牙组件以在 Android 中运行。为了在蓝牙连接的另一端初始化设备,我InitRelay从 C 代码调用。

这是原始的 C 代码(尚未进行任何更改):

fp_setbaud RelayAPI_SetBaud;
fp_get RelayAPI_get;
fp_put RelayAPI_put;
fp_flush RelayAPI_flush;
fp_delay RelayAPI_delay;
fp_ProgressUpdate RelayAPI_ProgressUpdateTX;
fp_ProgressUpdate RelayAPI_ProgressUpdateRX;
...

BYTE __stdcall InitRelay(fp_setbaud _setbaud, fp_get _get, fp_put _put, fp_flush _flush, fp_delay _delay){

    RelayAPI_SetBaud=_setbaud;
    RelayAPI_get=_get;
    RelayAPI_put=_put;
    RelayAPI_flush=_flush;
    RelayAPI_delay=_delay;
    ...
}

fp_* 函数在.h文件中的类型定义如下:

typedef void (__stdcall *fp_setbaud)(WORD);
typedef short (__stdcall *fp_get)(WORD);
typedef void (__stdcall *fp_put)(BYTE);
typedef void (__stdcall *fp_flush)(void);
typedef void (__stdcall *fp_delay)(WORD);
//typedef void (__stdcall *fp_err)(WORD);
typedef short (__stdcall *fp_ProgressUpdate)(WORD);

main methodold C program,InitRelay() 调用如下:

InitRelay(Changeit,getit,putit,flushit,delayit);

传递的参数是在 main 方法中定义的函数。我已经用 Java 重写了所有这些函数,并创建了一个新的 C 方法,如下所示:

jmethodID RelayAPI_SetBaud;
jmethodID RelayAPI_get;
jmethodID RelayAPI_put;
jmethodID RelayAPI_flush;
jmethodID RelayAPI_delay;
jmethodID RelayAPI_ProgressUpdateTX;
jmethodID RelayAPI_ProgressUpdateRX;
jclass    bluetoothClass;

BYTE __stdcall InitRelayJava( JNIEnv *env, jobject obj  ) {
    bluetoothClass = (*env)->GetObjectClass( env, obj );

    RelayAPI_SetBaud=(*env)->GetMethodID( env, bluetoothClass, "changeitJava", "(I)Z"  );
    RelayAPI_get    =(*env)->GetMethodID( env, bluetoothClass, "getitJava"   , "()V"   );
    RelayAPI_put    =(*env)->GetMethodID( env, bluetoothClass, "putitJava"   , "([B)V" );
    RelayAPI_flush  =(*env)->GetMethodID( env, bluetoothClass, "flushitJava" , "()V"   );
    RelayAPI_delay  =(*env)->GetMethodID( env, bluetoothClass, "delayitJava" , "(I)V"  );
    ...
}

当我尝试编译它时,我收到了数千个关于我的所有 RelayAPI_* 成员都不是函数的错误。这是一个屏幕截图:

在此处输入图像描述

我也被告知要添加这个函数来创建一个JVM,但我真的一点也不明白......

JNIEnv* create_vm( JavaVM ** jvm ) {
    JNIEnv *env;
    JavaVMInitArgs vm_args;

    JavaVMOption options;

    options.optionString = "-Djava.class.path=C:\\Users\\andrew\\workspace\\Singleton2\\src\\my\\eti\\commander";
    vm_args.version = JNI_VERSION_1_7;
    vm_args.nOptions = 1;
    vm_args.options = &options;
    vm_args.ignoreUnrecognized = 0;
    int ret = JNI_CreateJavaVM( jvm, (void**)&env, &vm_args );
    if( ret < 0 ) 
        printf( "\nUnable to Launch JVM\n" );
    return env;
}

告诉我编写上述函数的教程在这里...

所以,我不确定我做错了什么。我假设GetMethodID调用实际上并没有返回方法本身......有谁知道还能做什么?我一直在阅读教程,有一些关于 a 的内容,CallVoidMethod但我不明白……这是教程的链接……

请让我知道你在想什么。

4

1 回答 1

1

对于 void 方法,例如您的RelayAPI_flush方法。

如果您在 JNI 中有您的 Java 类,jobject bluetoothClass并且您jmethodID通过调用获得了该类的方法

RelayAPI_flush = env->GetMethodID(bluetoothClass, "flushitJava" , "()V");

然后,您可以像这样调用 JavaflushitJava函数:

env->CallVoidMethod(bluetoothClass, RelayAPI_flush);

您可能还必须正确地将线程附加到 VM 或从 VM 分离线程,网上有关于在 Android 中使用 JNI 的教程。

对于我们在 JNI 中的其他方法,根据http://java.sun.com/docs/books/jni/html/functions.html

Call<Type>Method
<NativeType>
CallVoidMethod
void
CallObjectMethod
jobject
CallBooleanMethod
jboolean
CallByteMethod
jbyte
CallCharMethod
jchar
CallShortMethod
jshort
CallIntMethod
jint
CallLongMethod
jlong
CallFloatMethod
jfloat
CallDoubleMethod
jdouble
于 2012-07-26T14:14:37.423 回答