Procházet zdrojové kódy

feat: 支持无参数和无返回值的形式调用clib函数

link #9
SongZihuan před 4 roky
rodič
revize
eda41541a1

+ 3 - 0
VirtulMathCore/include/value.h

@@ -64,10 +64,12 @@ struct Function{
     enum {
         c_func,
         vm_func,
+        f_func,
     } type;
     struct Statement *function;
     struct Parameter *pt;
     OfficialFunction of;
+    void (*ffunc)();  // ffi导入的func
     struct {
         enum FunctionPtType {
             free_,  // 不包含任何隐式传递的参数
@@ -225,6 +227,7 @@ Value *makeStringValue(wchar_t *str, fline line, char *file, FUNC_NT);
 Value *makeVMFunctionValue(struct Statement *st, struct Parameter *pt, FUNC_NT);
 Value *makeCFunctionValue(OfficialFunction of, fline line, char *file, FUNC_NT);
 LinkValue *makeCFunctionFromOf(OfficialFunction of, LinkValue *func, OfficialFunction function_new, OfficialFunction function_init, LinkValue *belong, VarList *var_list, Inter *inter);
+Value *makeFFunctionValue(void (*ffunc)(), fline line, char *file, FUNC_NT);
 Value *makeClassValue(VarList *var_list, Inter *inter, Inherit *father);
 Value *makeListValue(Argument *arg, fline line, char *file, enum ListType type, FUNC_NT);
 Value *makeDictValue(Argument *arg, bool new_hash, fline line, char *file, FUNC_NT);

+ 50 - 1
VirtulMathCore/ofunc/src/lib_.c

@@ -46,12 +46,13 @@ ResultType lib_init(O_FUNC){
     if (handle == NULL) {
         wchar_t *tmp = memWidecat(L"load lib error: ", memStrToWcs(dlerror(), false), false, true);
         setResultError(E_ImportException, tmp, LINEFILE, true, CNEXT_NT);
+        memFree(tmp);
         goto return_;
     }
     clib->value->data.lib.handle = handle;
 
     {
-        void (*test)(void) = dlsym(handle, "init");
+        void (*test)(void) = dlsym(handle, "init");  // 运行init函数
         if (test != NULL)
             test();
     }
@@ -86,9 +87,57 @@ ResultType lib_close(O_FUNC){
     return result->type;
 }
 
+ResultType lib_add(O_FUNC){
+    ArgumentParser ap[] = {{.type=only_value, .must=1, .long_arg=false},
+                           {.type=name_value, .name=L"func", .must=1, .long_arg=false},
+                           {.must=-1}};
+    LinkValue *clib;
+    char *name;
+    void (*func)();
+    setResultCore(result);
+    parserArgumentUnion(ap, arg, CNEXT_NT);
+    if (!CHECK_RESULT(result))
+        return result->type;
+    freeResult(result);
+
+    if ((clib = ap[0].value)->value->type != V_lib || clib->value->data.lib.handle == NULL) {
+        setResultError(E_TypeException, INSTANCE_ERROR(clib), LINEFILE, true, CNEXT_NT);
+        return R_error;
+    }
+
+    if (ap[1].value->value->type != V_str) {
+        setResultError(E_TypeException, ONLY_ACC(func, str), LINEFILE, true, CNEXT_NT);
+        return R_error;
+    }
+
+    name = memWcsToStr(ap[1].value->value->data.str.str, false);
+    func = dlsym(clib->value->data.lib.handle, name);
+    if (func == NULL) {
+        wchar_t *tmp = memWidecat(L"function not found: ", memStrToWcs(dlerror(), false), false, true);
+        setResultError(E_NameExceptiom, tmp, LINEFILE, true, CNEXT_NT);
+        memFree(tmp);
+    } else
+        makeFFunctionValue(func, LINEFILE, CFUNC_NT(var_list, result, clib));
+    memFree(name);
+
+    {
+        Result tmp;
+        setResultCore(&tmp);
+        addAttributes(ap[1].value->value->data.str.str, false, result->value, LINEFILE, false, CFUNC_NT(var_list, &tmp, clib));
+        if (!RUN_TYPE(tmp.type)) {
+            freeResult(result);
+            *result = tmp;
+        } else
+            freeResult(&tmp);
+    }
+
+    return result->type;
+}
+
 void registeredLib(R_FUNC){
     LinkValue *object = inter->data.lib_;
     NameFunc tmp[] = {{L"close", lib_close, object_free_},
+                      {L"add", lib_add, object_free_},
                       {inter->data.object_new, lib_new, class_free_},
                       {inter->data.object_init, lib_init, object_free_},
                       {inter->data.object_del, lib_close, object_free_},

+ 30 - 5
VirtulMathCore/src/runcall.c

@@ -257,6 +257,19 @@ static ResultType callCFunction(LinkValue *function_value, Argument *arg, long i
     return result->type;
 }
 
+static ResultType callFFunction(LinkValue *function_value, Argument *arg, long int line, char *file, int pt_sep, FUNC_NT){
+    ffi_cif cif;
+    setResultCore(result);
+    gc_addTmpLink(&function_value->gc_status);
+
+    ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &ffi_type_void, NULL);
+    ffi_call(&cif, function_value->value->data.function.ffunc,  NULL, NULL);
+
+    setResult(result, inter);
+    gc_freeTmpLink(&function_value->gc_status);
+    return result->type;
+}
+
 static void updateFunctionYield(Statement *func_st, Statement *node){
     func_st->info.node = node->type == yield_code ? node->next : node;
     func_st->info.have_info = true;
@@ -342,16 +355,28 @@ static ResultType callVMFunction(LinkValue *func_value, Argument *arg, long int
 ResultType callBackCore(LinkValue *function_value, Argument *arg, fline line, char *file, int pt_sep, FUNC_NT) {
     setResultCore(result);
     gc_addTmpLink(&function_value->gc_status);
-    if (function_value->value->type == V_func && function_value->value->data.function.type == vm_func)
-        callVMFunction(function_value, arg, line, file, pt_sep, CNEXT_NT);
-    else if (function_value->value->type == V_func && function_value->value->data.function.type == c_func)
-        callCFunction(function_value, arg, line, file, pt_sep, CNEXT_NT);
-    else if (function_value->value->type == V_class)
+    if (function_value->value->type == V_func) {
+        switch (function_value->value->data.function.type) {
+            case vm_func:
+                callVMFunction(function_value, arg, line, file, pt_sep, CNEXT_NT);
+                break;
+            case c_func:
+                callCFunction(function_value, arg, line, file, pt_sep, CNEXT_NT);
+                break;
+            case f_func:
+                callFFunction(function_value, arg, line, file, pt_sep, CNEXT_NT);
+                break;
+            default:
+                setResultError(E_SystemException, L"function type error", line, file, true, CNEXT_NT);
+                goto return_;
+        }
+    } else if (function_value->value->type == V_class)
         callClass(function_value, arg, line, file, pt_sep, CNEXT_NT);
     else
         callObject(function_value, arg, line, file, pt_sep, CNEXT_NT);
     setResultError(E_BaseException, NULL, line, file, false, CNEXT_NT);
 
+    return_:
     gc_freeTmpLink(&function_value->gc_status);
     return result->type;
 }

+ 20 - 4
VirtulMathCore/src/value.c

@@ -87,8 +87,7 @@ Value *makeStringValue(wchar_t *str, fline line, char *file, FUNC_NT) {
 
 Value *makeVMFunctionValue(Statement *st, Parameter *pt, FUNC_NT) {
     Value *tmp = NULL;
-    callBackCore(inter->data.function, NULL, st->line, st->code_file, 0,
-                 CNEXT_NT);
+    callBackCore(inter->data.function, NULL, st->line, st->code_file, 0, CNEXT_NT);
     if (!CHECK_RESULT(result))
         return NULL;
     tmp = result->value->value;
@@ -106,8 +105,7 @@ Value *makeVMFunctionValue(Statement *st, Parameter *pt, FUNC_NT) {
 
 Value *makeCFunctionValue(OfficialFunction of, fline line, char *file, FUNC_NT) {
     Value *tmp = NULL;
-    callBackCore(inter->data.function, NULL, line, file, 0,
-                 CNEXT_NT);
+    callBackCore(inter->data.function, NULL, line, file, 0, CNEXT_NT);
     if (!CHECK_RESULT(result))
         return NULL;
     tmp = result->value->value;
@@ -124,6 +122,24 @@ Value *makeCFunctionValue(OfficialFunction of, fline line, char *file, FUNC_NT)
     return tmp;
 }
 
+Value *makeFFunctionValue(void (*ffunc)(), fline line, char *file, FUNC_NT) {
+    Value *tmp = NULL;
+    callBackCore(inter->data.function, NULL, line, file, 0, CNEXT_NT);
+    if (!CHECK_RESULT(result))
+        return NULL;
+    tmp = result->value->value;
+    tmp->data.function.type = f_func;
+    tmp->data.function.ffunc = ffunc;
+    tmp->data.function.function_data.cls = belong;
+    for (VarList *vl = tmp->object.out_var, *vl_next; vl != NULL; vl = vl_next) {
+        vl_next = vl->next;
+        freeVarList(vl);
+    }
+    tmp->object.out_var = copyVarList(var_list, false, inter);
+    result->value->belong = belong;
+    return tmp;
+}
+
 LinkValue *makeCFunctionFromOf(OfficialFunction of, LinkValue *func, OfficialFunction function_new, OfficialFunction function_init, LinkValue *belong, VarList *var_list, Inter *inter) {
     Argument *arg = makeValueArgument(func);
     Argument *init_arg = NULL;