mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2025-12-06 02:40:26 -08:00
132 lines
4 KiB
C
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;
|
|
};
|