私のアプリケーションはネイティブ ライブラリを呼び出し、次にネイティブ ライブラリ内で Java コードを呼び出します。ネイティブライブラリへの呼び出しは正しく機能していますが(私はかなり確信しています)、CファイルからJava関数を呼び出そうとしたときにJava関数が見つからないことを教えてくれません。
アプリケーションはクラッシュすることさえありません。予期せず終了したことを知らせるポップアップはありません。黒い画面が点滅するだけで、何も起こりません。
私が再現しようとしているコードは、もともと Palm Pilot 用に C で作成されたもので、Android デバイスに転送されています。これは、複製しようとしている CI の元の呼び出しです...
InitRelay(Changeit,getit,putit,flushit,delayit);
上記の呼び出しのパラメーターは関数名です。関数は以下のとおりです。
void Changeit(WORD baud){
ChangeRate(baud);
}
extern Boolean ChangeRate(UInt32 baud)
{...}
Int16 getit(UInt16 t) {...}
void putit( BYTE p ) {...}
void flushit(void){...}
extern void delayit( UInt16 wait ) {...}
.c
これは、私のファイルに示されている InitRelayです。
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;
....
}
上記のパラメーターは、私の.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);
WORD/BYTE/DWORD
タイプは、次に.h
示す別のファイルで定義されます。
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
ここで、Android コードで、作成した InitRelayJava() という関数を呼び出します。アプリケーションのすべてのデータは、 という別のクラスに格納されRelayAPIModel
ます。その中にネストされたクラスを作成して、すべてのネイティブ関数を格納しました。これは、アプリケーションが現在どのアクティビティにあるかに関係なく、これらの関数に同じ方法でアクセスできるようにするためです。
public class RelayAPIModel {
....
public static class NativeCalls {
static {
System.loadLibrary( "RelayAPI" );
}
public native static byte InitRelayJava();
public native static void FreeRelayJava();
public static void changeItJavaWrapper( short l ) {
mModelService.changeitJava( l );
}
public static void flushItJavaWrapper() {
mModelService.flushitJava();
}
public static void putItJavaWrapper( byte[] p ) {
mModelService.putitJava( p );
}
public static void delayItJavaWrapper( short wait ) {
mModelService.delayitJava( wait );
}
public static short getItJavaWrapper( short s ) {
return mModelService.getitJava( s );
}
}
}
関数内で行われた呼び出しは*Wrapper
、アプリケーションのすべての Bluetooth 機能を処理する必要がある別のクラスに送られます。この問題にはそれらが必要だとは思いません。
これは私のCコードでInitRelayJavaがどのように見えるかです...
BYTE Java_my_eti_commander_RelayAPIModel_00024NativeCalls_InitRelayJava( JNIEnv *env, jobject obj ) {
myEnv = (env);
bluetoothClass = (*env)->GetObjectClass( env, obj );
myObject = obj;
changeID = (*myEnv)->GetMethodID( myEnv, myObject, "changeitJavaWrapper", "(S)V" );
getID = (*myEnv)->GetMethodID( myEnv, myObject, "getitJavaWrapper" , "(S)S" );
putID = (*myEnv)->GetMethodID( myEnv, myObject, "putitJavaWrapper" , "(B)V" );
flushID = (*myEnv)->GetMethodID( myEnv, myObject, "flushitJavaWrapper" , "()V" );
delayID = (*myEnv)->GetMethodID( myEnv, myObject, "delayitJavaWrapper" , "(S)V" );
...
}
これは私が受け取っている LogCat です...
08-02 10:27:32.406: D/dalvikvm(28376): Trying to load lib /data/data/my.eti.commander/lib/libRelayAPI.so 0x40515430
08-02 10:27:32.406: D/dalvikvm(28376): Added shared lib /data/data/my.eti.commander/lib/libRelayAPI.so 0x40515430
08-02 10:27:32.406: D/dalvikvm(28376): No JNI_OnLoad found in /data/data/my.eti.commander/lib/libRelayAPI.so 0x40515430, skipping init
08-02 10:27:32.406: D/dalvikvm(28376): GetMethodID: method not found: Lmy/eti/commander/RelayAPIModel$NativeCalls;.changeitJavaWrapper:(S)V
08-02 10:27:32.413: D/dalvikvm(28376): GetMethodID: method not found: Lmy/eti/commander/RelayAPIModel$NativeCalls;.getitJavaWrapper:(S)S
08-02 10:27:32.413: E/dalvikvm(28376): Class lookup Ljava/lang/NoSuchMethodError; attempted while exception Ljava/lang/NoSuchMethodError; pending