|
Technote 1155JNI Tips: Building Your Native-Method Libraries For MacOSBy Jens Alfke |
CONTENTSI'm Superunsatisfied! | J NI (Java Native Interface) is a cross-platform standard for implementing Java methods in native code. MRJ 2.0 and 2.1 support JNI; however, some developers run into trouble getting their JNI libraries to work correctly on Mac OS. For the most part these are build- and installation-related issues. This Technote is designed to put you at ease. |
Exporting The Right StuffFor MRJ to find the right functions to call in your library, they need to be exported. The linker needs to know which functions to export when it links the library. The documentation for your development system (probably either MPW or CodeWarrior) will describe in detail how to set up exports. There are basically two ways to do it: Use a .exp file. One way to set up exports is via a separate .exp file, which is a text file that contains the names of the exported functions, one per line. If using CodeWarrior, you add the .exp file to your project, then go to the PPC PEF panel of the Project Settings dialog and set the Export pop-up to Use '.exp' File. If using MPWs If you use a .exp file, make sure that you spell all the function names correctly (pasting them in from your source files is the best bet) and be sure to keep the file in sync when you add, remove, or rename native methods -- or if any parameters change. Use #pragma export. The other method -- which I prefer -- is to use a C/C++
Another equivalent way to mark the functions for export is to use the standard
You then need to tell the linker to export marked functions. If using CodeWarrior, go to the PPC PEF panel of the Project Settings dialog and set the Export pop-up to Use #pragma. If using MPWs The advantage of using the second technique is that it always exports the correct functions, even if the set of native methods change. All you have to do is re-run java.h (or recompile your Java classes, if you're using CodeWarriors option to emit JNI headers) and the list of exported functions will automatically be updated next time you build your native library. |
Positioning The LibraryFinally, even if your library is built perfectly, it wont do much good if MRJ cant find it. The library file needs to be on the CFM search path. Basically, this means that it needs to be:
The application, of course, can mean a JBindery-generated application, a browser like Microsoft Internet Explorer, or Apple Applet Runner. (Note that if you're running your code directly from JBindery without saving the settings as an app, then the application means JBindery itself). If your native code is being used by a specific application, then the usual place to put the library is into the same folder as the app. If your native code is part of a shared Java library thats installed in the MRJClasses folder, then the native library should go into the MRJ Libraries folder (not the MRJClasses folder, for reasons described above). Embedding the code fragment within the application itself is tempting, especially since -- if combined with a Virtual File System -- you can boil your whole app down to a single file. Since the data fork is already in use by the VFS, the best place to put the code fragment is into a resource. You'll have to tell the linker to generate a code resource, then copy the resource into the app and add a new entry to the apps |
Debugging The Loading ProcessIf you have a pesky native library that just flat-out refuses to load even after you've used all the previous information to troubleshoot it, heres a way to debug some of the loading process. (You must have MacsBug installed to do this. Technote 1154, Debugging Java Code With MacsBug, has an introduction to MacsBug for Java developers.)
|
Further References
|
AcknowledgmentsThanks to Nick Kledzik for reviewing this Technote and suggesting additional tips, and to kelly jacklin for extra JNI info. |