title: Why can't my C code find my Java functions?
body: <p>My application makes calls to a native library, and then within the native library, makes calls back to the Java code. I have the calls TO the native library working correctly ( I'm pretty sure ), but not its telling me that it can't find the Java functions when trying to call them from the C file. </p>
  
  <p>The application doesn't even crash, there is no pop up telling me it closed unexpectedly, it just flashes a black screen and nothing happens.</p>
  
  <p>The code I am trying to reproduce was originally made in C for Palm Pilot, and is being transferred to an Android device. This is the original call in C I am trying to duplicate...</p>
  
  <pre><code>InitRelay(Changeit,getit,putit,flushit,delayit);
  </code></pre>
  
  <p>The parameters in the call above are function names, the functions are here below: </p>
  
  <pre><code>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 ) {...}
  </code></pre>
  
  <p>This is InitRelay shown in my <code>.c</code> file:</p>
  
  <pre><code>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;
      ....
  }
  </code></pre>
  
  <p>The parameters shown in above are typedefed in my <code>.h</code> file:</p>
  
  <pre><code>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);
  </code></pre>
  
  <p>The <code>WORD/BYTE/DWORD</code> types are defined in a separate <code>.h</code> file shown here:</p>
  
  <pre><code>typedef unsigned char BYTE;
  typedef unsigned short WORD;
  typedef unsigned long DWORD;
  </code></pre>
  
  <p>Now, in my Android code, I call a function I made called InitRelayJava(), all of my data for the application is stored in a separate class called <code>RelayAPIModel</code>. I created a nested class within that to store all of my native functions. I did this so that I can access these functions the same way no matter what Activity the application is currently in.</p>
  
  <pre><code>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 );
          }
      }
   }
  </code></pre>
  
  <p>The calls made inside the <code>*Wrapper</code> functions go to a separate class that I have to handle all of the applications bluetooth capabilities. I do not think that those are needed for this problem. </p>
  
  <p>This is what InitRelayJava looks like in my C code...</p>
  
  <pre><code>BYTE Java_my_eti_commander_RelayAPIModel_00024NativeCalls_InitRelayJava( JNIEnv *env, jobject obj  ) {
  
      myEnv = (env);
      bluetoothClass = (*env)-&gt;GetObjectClass( env, obj );
      myObject = obj;
  
      changeID = (*myEnv)-&gt;GetMethodID( myEnv, myObject, "changeitJavaWrapper", "(S)V"  );
      getID    = (*myEnv)-&gt;GetMethodID( myEnv, myObject, "getitJavaWrapper"   , "(S)S"   );
      putID    = (*myEnv)-&gt;GetMethodID( myEnv, myObject, "putitJavaWrapper"   , "(B)V" );
      flushID  = (*myEnv)-&gt;GetMethodID( myEnv, myObject, "flushitJavaWrapper" , "()V"   );
      delayID  = (*myEnv)-&gt;GetMethodID( myEnv, myObject, "delayitJavaWrapper" , "(S)V"  );
  ...
  }
  </code></pre>
  
  <p>This is the LogCat I am receiving...</p>
  
  <pre><code>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
  </code></pre>