Advertisement
Guest User

Untitled

a guest
Sep 15th, 2012
191
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  *  This method has been tested on Linux running Ubuntu 12.04
  3.  *
  4.  *  1. Download the Android NDK: http://developer.android.com/tools/sdk/ndk/index.html
  5.  *  2. Extract it somewhere.
  6.  *  3. Download eNet source: http://enet.bespin.org/SourceDistro.html
  7.  *  4. Make a new directory in your Java project's root folder called 'jni'.
  8.  *  5. Extract the eNet source into that directory. If it makes an enet-1.3.5/ directory
  9.  *     inside it, move all the files and folders from enet-1.3.5/ dirtectory to jni/
  10.  *  6. Move all the header files from include/ to the jni/ directory.
  11.  *     The jni/ directory should now contain the following files and folders:
  12.  *
  13.  *     aclocal.m4 ChangeLog config.sub depcomp enet enet.dsp install-sh LICENSE m4 missing  
  14.  *     protocol.c compress.c configure docs enet64.lib enet.lib list.c Makefile.am packet.c
  15.  *     README win32.c callbacks.c config.guess configure.ac Doxyfile enet_dll.cbp host.c
  16.  *     libenet.pc.in ltmain.sh Makefile.in peer.c unix.c
  17.  *
  18.  *     where enet docs and m4 are directories.
  19.  *  7. Create a jni-wrapper.c file with the following contents:
  20.  */
  21.  
  22. /* FILE: jni-wrapper.c */
  23. #include "enet/enet.h"
  24. #include "jni.h"
  25.  
  26. /* Get your class' mangled function names with:
  27.  * $ javah -classpath /home/vladimir/workspace/TestEnet/bin/classes/ com.example.testenet.MainActivity
  28.  * javah takes -classpath switch. Replace the directory following it with with your project's one.
  29.  * The second argument is the classpath. You can cd to the directory that contains the .java
  30.  * file that declares a native function. In your case, you want to add a
  31.  *
  32.  * public native int enet_initialize();
  33.  *
  34.  * declaration to your .java file **BEFORE** you execute this command.
  35.  * In my case, this produced a com_example_testenet_MainActivity.h file in the
  36.  * src/com/example/testenet/ directory.
  37.  */
  38.  
  39. /* You will probably need this. You can call enet_initialize() from here if you want
  40.  * the library to initialize when you load it inside your Java application.
  41.  */
  42. jint JNI_OnLoad
  43. (JavaVM *vm, void *reserved)
  44. {
  45.     printf("Hello, world!\n");
  46.    
  47.     return JNI_VERSION_1_6;
  48. }
  49.  
  50. /* Now we come to the dreadful name mangling. Calling externally defined (native) functions
  51.  * in Java is not as simple as declaring a function native and loading a correct library.
  52.  * The function name must be propperly formed so that the JavaVM can find it. You can
  53.  * devise this name by yourself. it starts with Java_ then follows the classpath
  54.  * divided with underscores and finally, the function name. If a declared native function
  55.  * also contains an underscore, instead of enet__initialize for example, you write
  56.  * enet_1initialize.
  57.  *
  58.  * javah utility does all this name mangling for you.
  59.  *
  60.  */
  61. JNIEXPORT jint JNICALL /* This declaration enables the JavaVM to find this function.
  62.                         * It returns a jint (because you put int as a return type in the
  63.                         * function declaration in your .java file.)
  64.                         */
  65. Java_com_example_testenet_MainActivity_enet_1initialize /* This is the mangled name. It will
  66.                                                          * allow the VM to correctly call
  67.                                                          * **THIS** function when you call
  68.                                                          * enet_initialize() inside your
  69.                                                          * Java class.
  70.                                                          */
  71. (JNIEnv *env, jobject obj) /* This is what javah generated for us. If a function had an int
  72.                            * as an argument, the declaration would be (JNIEnv *env, jclass
  73.                            * cls, int anInt). You use these for all sorts of things, but they
  74.                            * are not used in this particular function.
  75.                            */
  76. {
  77.     // Now we're inside the wrapper function.
  78.     printf("CALLING enet_initialize()...\n");
  79.     return enet_initialize(); /* This works because jint (what our function is upposed to
  80.                                    * return) is just typdefed int. More complex stuff requires
  81.                                    * more complex approach.
  82.                                    */
  83. }
  84.  
  85. /* END FILE */
  86.  
  87.  
  88. /*  8. Create and Andorid.mk file inside the jni/ directory with the following contents:
  89.  *     (This is actually just copied from a NDK sample app. I omitted the licence comment
  90.  *     block. Hope I won't be sued for this :))
  91.  *
  92.  * FILE: Android.mk */
  93.  
  94. LOCAL_PATH := $(call my-dir)
  95.  
  96. include $(CLEAR_VARS)
  97.  
  98. LOCAL_MODULE    := enet-jni
  99. LOCAL_SRC_FILES := callbacks.c  compress.c  host.c  list.c  packet.c  peer.c  protocol.c  unix.c  win32.c  jni-wrapper.c
  100.  
  101. include $(BUILD_SHARED_LIBRARY)
  102.  
  103. /* END FILE
  104.  *
  105.  *     As you can see, it contains all the .c files currently in the jni/ directory,
  106.  *     including the jni-wrapper.c file we created previously.
  107.  *  9. cd to the directory where you extracted the Android NDK files.
  108.  * 10. Export the Android project's path to the NDK_BUILD_VARIABLE:
  109.  *     $ export NDK_BUILD_VARIABLE=/home/vladimir/workspace/TestEnet/
  110.  * 11. Execute the ndk-build command:
  111.  *     $ ./ndk-build
  112.  *     It should compile and link it successfully.
  113.  * 12. Now you can add:
  114.  
  115.     static {
  116.         System.loadLibrary("enet-jni");
  117.     }
  118.  
  119.  *     to your .java file. This is how mine looks (I used a New Android Project from Eclipse):
  120.  
  121.  * FILE: MainActivity.java */
  122.  
  123. package com.example.testenet;
  124.  
  125. import android.os.Bundle;
  126. import android.app.Activity;
  127. import android.view.Menu;
  128. import android.widget.TextView;
  129.  
  130. public class MainActivity extends Activity {
  131.  
  132.     @Override
  133.     public void onCreate(Bundle savedInstanceState) {
  134.         super.onCreate(savedInstanceState);
  135.        
  136.         TextView tv = new TextView(this);
  137.        
  138.         if (enet_initialize() != 0)
  139.             tv.setText("Error!");
  140.         else
  141.             tv.setText("Enet initialized.");
  142.         setContentView(tv);
  143.     }
  144.  
  145.     @Override
  146.     public boolean onCreateOptionsMenu(Menu menu) {
  147.         getMenuInflater().inflate(R.menu.activity_main, menu);
  148.         return true;
  149.     }
  150.    
  151.     public native int enet_initialize();
  152.    
  153.     static {
  154.         System.loadLibrary("enet-jni");
  155.     }
  156. }
  157.  
  158. /* END FILE
  159.  *
  160.  * I went through much trouble trying to get it work, but when I set everything up right,
  161.  * I ran this example project and was greeted with a "Enet initialized." message on the
  162.  * emulator screen. Of course, this is just very, very basic stuff (in unix.c, I saw that
  163.  * it's implementation of enet_initialize(), simply returns a 0 :). So, if you were to
  164.  * embark on the adventure of wrapping the existing eNet library with jni to include in your
  165.  * project, you are probably wondering if it's worth it. Quite honestly, I don't think it is.
  166.  * You are better off using different libraries for that.
  167.  * But you will learn a lot if you decide to manually do it (try implementing only the basic
  168.  * stuff you'd need for a client - you don't need to wrap all of the libraries functions, just
  169.  * the one's you'd end up using in your project). Now, if you are interested, you are
  170.  * probably wondering how can one pass more complex stuff between the Java app and the module.
  171.  * I am not that skilled to answer you that, but I've included some links that should be
  172.  * enough to get you started. Enjoy :)
  173.  
  174.  * LINKS:
  175.  
  176. http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html
  177. http://www.steveolyo.com/JNI/JNI.html
  178. http://stackoverflow.com/questions/3923299/how-to-pass-c-structs-back-and-forth-to-java-code-in-jni
  179. http://www.ibm.com/developerworks/java/library/j-jni/
  180.  */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement