diff --git a/src/ecl_fun.cpp b/src/ecl_fun.cpp index 2aa8c2f..982091f 100644 --- a/src/ecl_fun.cpp +++ b/src/ecl_fun.cpp @@ -145,6 +145,7 @@ void iniCLFunctions() { DEFUN ("qfrom-utf8", qfrom_utf8, 1) DEFUN ("qid", qid, 1) DEFUN ("%qinvoke-method", qinvoke_method2, 4) + DEFUN ("qjs-call", qjs_call, 3) DEFUN ("%qload-c++", qload_cpp, 2) DEFUN ("qload-ui", qload_ui, 1) DEFUN ("qlocal8bit", qlocal8bit, 1) @@ -962,6 +963,30 @@ static QVariantList toQVariantList(cl_object l_list) { l_el = cl_cdr(l_el); }} return l; } +static QVariantList lispToQVariantList(cl_object l_list) { + // converts (nested) Lisp lists to (nested) QVariant lists + QVariantList l; + if(LISTP(l_list)) { + cl_object l_do_list = l_list; + while(l_do_list != Cnil) { + cl_object l_el = cl_car(l_do_list); + if(cl_integerp(l_el) == ECL_T) { // int + l << QVariant(toInt(l_el)); } + else if(cl_floatp(l_el) == ECL_T) { // double + l << QVariant(toFloat(l_el)); } + else if(cl_stringp(l_el) == ECL_T) { // string + l << QVariant(toQString(l_el)); } + else if(l_el == ECL_T) { // true + l << QVariant(true); } + else if(l_el == ECL_NIL) { // null + l << QVariant(); } + else if(LISTP(l_el)) { // list + l << QVariant::fromValue(lispToQVariantList(l_el)); } + else { // null + l << QVariant(); } + l_do_list = cl_cdr(l_do_list); }} + return l; } + static cl_object from_char(char ch) { cl_object l_char = cl_code_char(MAKE_FIXNUM((int)ch)); return l_char; } @@ -3021,6 +3046,47 @@ cl_object qlog2(cl_object l_msg) { qDebug() << toQString(l_msg); return Cnil; } +cl_object qjs_call(cl_object l_item, cl_object l_name, cl_object l_args) { + // direct, fast JS calls, see 'qml-lisp' in QML examples + // max. 10 arguments + // supported argument types: T, NIL, INTEGER, FLOAT, STRING, (nested) LIST of mentioned arguments + ecl_process_env()->nvalues = 1; + QVariant arg[10]; + QGenericArgument genA[10]; + const char* v = "QVariant"; + cl_object l_do_args = l_args; + int i = 0; + for(; l_do_args != Cnil; i++) { + cl_object l_arg = cl_car(l_do_args); + if(cl_integerp(l_arg) == ECL_T) { // int + arg[i] = QVariant(toInt(l_arg)); } + else if(cl_floatp(l_arg) == ECL_T) { // double + arg[i] = QVariant(toFloat(l_arg)); } + else if(cl_stringp(l_arg) == ECL_T) { // string + arg[i] = QVariant(toQString(l_arg)); } + else if(l_arg == ECL_T) { // true + arg[i] = QVariant(true); } + else if(l_arg == ECL_NIL) { // null + arg[i] = QVariant(); } + else if(LISTP(l_arg)) { // list + arg[i] = QVariant::fromValue(lispToQVariantList(l_arg)); } + else { // default: null + arg[i] = QVariant(); } + genA[i] = QGenericArgument(v, &arg[i]); + l_do_args = cl_cdr(l_do_args); } + QGenericArgument null; + for(; i < 10; i++) { + genA[i] = null; } + QtObject o = toQtObject(l_item); + QVariant ret; + QGenericReturnArgument genR(v, &ret); + if(o.isQObject()) { + QMetaObject::invokeMethod((QObject*)o.pointer, toCString(l_name), genR, + genA[0], genA[1], genA[2], genA[3], genA[4], genA[5], genA[6], genA[7], genA[8], genA[9]); + return from_qvariant_value(ret); } + error_msg("QJS-CALL", LIST3(l_item, l_name, l_args)); + return ECL_NIL; } + // *** special extensions *** diff --git a/src/ecl_fun.h b/src/ecl_fun.h index 2bf5ffa..bcd7769 100644 --- a/src/ecl_fun.h +++ b/src/ecl_fun.h @@ -259,6 +259,7 @@ cl_object qfind_children2 (cl_object, cl_object, cl_object); cl_object qfrom_utf8 (cl_object); cl_object qid (cl_object); cl_object qinvoke_method2 (cl_object, cl_object, cl_object, cl_object); +cl_object qjs_call (cl_object, cl_object, cl_object); cl_object qload_cpp (cl_object, cl_object); cl_object qload_ui (cl_object); cl_object qlocal8bit (cl_object);