Examples of embedding CHICKEN
Minimal example of embedding CHICKEN in a regular C program
From the CHICKEN-users mailing list, a post by Felix.
This shows a minimal example of embedding (you don't need CHICKEN_initialize, unless you want to set specific buffer sizes):
/* gcc x.c -lchicken -o x */ #include <chicken.h> int main() { C_word x; CHICKEN_run(CHICKEN_default_toplevel); CHICKEN_eval_string("(print (+ 3 4))", &x); return 0; }
Embedding CHICKEN in an Android application
A quick way to make sense of all the moving parts is to start by copying samples/hello-jni from your NDK directory. Then you can alter hello-jni.c so it looks like this:
#include <string.h> #include <jni.h> #include <chicken.h> jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz ) { C_word res; char foo[100]; CHICKEN_run(CHICKEN_default_toplevel); CHICKEN_eval_string("(+ 2 5)", &res); snprintf(foo, 100, "Evaluation result: %d", C_unfix(res)); return (*env)->NewStringUTF(env, foo); }
Then, build CHICKEN using PLATFORM=android for your target architecture. You'll have to build a libchicken.so for each architecture you want to support. For simplicity, let's say for now that we only want to build for armeabi (which has no apply-hack at the time of writing, so we disable autodetection via "ARCH="):
$ make PLATFORM=android ARCH= C_COMPILER='/path/to/ndk/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc --sysroot=/path/to/ndk/platforms/android-16/arch-arm'
The above is according to "Invoking the compiler (the hard way)" from the docs/STANDALONE-TOOLCHAIN.html in the NDK's root. The easy way involves more steps and is harder to explain here. See the aforementioned document for more information.
In your copy of the sample program, alter jni/Application.mk to read APP_ABI := armeabi. Copy libchicken.so to jni/chicken/armeabi and copy chicken.h to jni/chicken/include.
Then, create a file jni/chicken/Android.mk containing the following:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := chicken LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libchicken.so LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include include $(PREBUILT_SHARED_LIBRARY)
Changejni/Android.mk so that the application will depend on libchicken, and pull in the new Makefile so it knows how to build it:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.c LOCAL_SHARED_LIBRARIES := chicken include $(BUILD_SHARED_LIBRARY) include $(LOCAL_PATH)/chicken/Android.mk
Finally, modify com/example/hellojni/HelloJni.java to load the chicken module before hello-jni is loaded:
static { System.loadLibrary("chicken"); System.loadLibrary("hello-jni"); }
You're all set!
To build, run /path/to/ndk/ndk-build and then ant debug to package up the program.
Extending this build to other ABI versions is simple: just add it to Application.mk and build different libchicken.so versions and install them under the correspondingly named subdirectory under jni/chicken/<ABI-NAME>/libchicken.so.