ecl/examples/android/jni/org_lisp_ecl_EmbeddedCommonLisp.c
2015-10-26 11:13:48 +01:00

132 lines
4 KiB
C

#include <assert.h>
#if ANDROID
#include <android/log.h>
#endif
#include <string.h>
#include <jni.h>
#include <pthread.h>
#include <stdio.h>
#include <ecl/ecl.h>
#include "ecl_boot.h"
#if ANDROID
#define ECL_TAG "ecl-native"
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, ECL_TAG, __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, ECL_TAG, __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, ECL_TAG, __VA_ARGS__))
#define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ECL_TAG, __VA_ARGS__))
#else
#define LOGI(...)
#define LOGW(...)
#define LOGE(...)
#endif
#define jni_ecl_read_from_string(x) si_string_to_object(1, x)
/*
* Class: org_lisp_ecl_EmbeddedCommonLisp
* Method: start
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_org_lisp_ecl_EmbeddedCommonLisp_start(JNIEnv *env, jobject this, jstring path) {
const char *lisp_dir = (*env)->GetStringUTFChars(env, path, NULL);
LOGI("XXX: ECL starting: *default-pathname-defaults* to: %s\n", lisp_dir);
ecl_boot(lisp_dir);
LOGI("ECL started.");
};
/* This was fun to make UTF8 work across Java-C-Lisp boundaries.
-evrim, 2014. */
cl_object java_string_to_ecl_string(JNIEnv *env, jstring str) {
const jchar *txt = (*env)->GetStringChars(env, str, NULL);
jsize len = (*env)->GetStringLength(env, str);
cl_object ecl_txt = ecl_alloc_simple_extended_string(len);
cl_index i;
for (i=0;i<len;i++) {
ecl_txt->string.self[i] = txt[i];
};
(*env)->ReleaseStringChars(env, str, txt);
return ecl_txt;
}
jstring ecl_object_to_java_string(JNIEnv *env, cl_object o) {
jstring ret;
if (ECL_EXTENDED_STRING_P(o)) {
LOGI("ecl->java extended string of fillp: %d, dim: %d",
o->string.fillp,
o->string.dim);
jsize len = o->string.fillp;
jchar *arr = malloc(sizeof(jchar)*(len+1));
cl_index i;
for (i=0; i<len; i++) {
arr[i] = o->string.self[i];
}
arr[len] = 0;
ret = (*env)->NewString(env, arr, len);
free(arr);
} else if (ECL_STRINGP(o)) {
LOGI("ecl->java base string of len %d: %s",
o->base_string.dim,
o->base_string.self);
ret = (*env)->NewStringUTF(env, (const char*)o->base_string.self);
} else {
LOGI("ecl->java not a string, coercing");
return ecl_object_to_java_string(env, cl_princ_to_string(o));
}
return ret;
}
/*
* Class: org_lisp_ecl_EmbeddedCommonLisp
* Method: exec
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
Java_org_lisp_ecl_EmbeddedCommonLisp_exec(JNIEnv *env, jobject this, jstring str) {
jstring ret;
cl_object txt = java_string_to_ecl_string(env, str);
cl_object result = si_safe_eval(3, jni_ecl_read_from_string(txt), Cnil, OBJNULL);
if (result) {
ret = ecl_object_to_java_string(env, result);
} else {
ret = (*env)->NewStringUTF(env, "ERROR in eval");
}
return ret;
};
#undef jni_ecl_read_from_string
/*
* Class: org_lisp_ecl_EmbeddedCommonLisp
* Method: exec_
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
Java_org_lisp_ecl_EmbeddedCommonLisp_exec_(JNIEnv *env, jobject this, jstring str) {
jstring ret;
const char *cmd = (*env)->GetStringUTFChars(env, str, NULL);
cl_object result = si_safe_eval(3, c_string_to_object(cmd),
Cnil, OBJNULL);
if (result) {
cl_object out = si_coerce_to_base_string(cl_princ_to_string(result));
ret = (*env)->NewStringUTF(env, (const char*) out->base_string.self);
} else {
ret = (*env)->NewStringUTF(env, "ERROR in eval");
}
return ret;
};