Browse Source

feat: 支持导入clib动态库

link #9
SongZihuan 4 years ago
parent
commit
0753b69852

+ 1 - 0
VirtulMathCore/include/inter.h

@@ -26,6 +26,7 @@ struct Inter{
         struct LinkValue *str;
         struct LinkValue *bool_;
         struct LinkValue *pass_;
+        struct LinkValue *lib_;
         struct LinkValue *file;
         struct LinkValue *tuple;
         struct LinkValue *list;

+ 1 - 0
VirtulMathCore/include/ofunc.h

@@ -16,6 +16,7 @@
 #include "dictiter.h"
 #include "error_.h"
 #include "file_.h"
+#include "lib_.h"
 
 struct Argument;
 struct VarList;

+ 6 - 0
VirtulMathCore/include/value.h

@@ -49,6 +49,7 @@ enum ValueType {
     V_bool=8,
     V_ell=9,
     V_file=10,
+    V_lib=11,
 };
 
 struct Number {
@@ -103,6 +104,10 @@ struct Bool{
     bool bool_;
 };
 
+struct Lib{
+    void *handle;
+};
+
 struct File{
     FILE *file;
     char *path;  // 文件路径
@@ -127,6 +132,7 @@ struct Value{
         struct Dict dict;
         struct Bool bool_;
         struct File file;
+        struct Lib lib;
     } data;
 
     struct Value *gc_next;

+ 5 - 0
VirtulMathCore/ofunc/include/lib_.h

@@ -0,0 +1,5 @@
+#ifndef VIRTUALMATH_LIB__H
+#define VIRTUALMATH_LIB__H
+void registeredLib(R_FUNC);
+void makeBaseLib(Inter *inter);
+#endif //VIRTUALMATH_LIB__H

+ 7 - 9
VirtulMathCore/ofunc/src/file_.c

@@ -168,16 +168,14 @@ ResultType file_close(O_FUNC){
         return R_error;
     }
 
-    if (file->value->data.file.file == NULL || file->value->data.file.is_std)
-        goto return_;
-
-    fclose(file->value->data.file.file);
-    file->value->data.file.file = NULL;
-    memFree(file->value->data.file.path);
-    memFree(file->value->data.file.mode);
-    file->value->data.file.is_std = true;
+    if (file->value->data.file.file != NULL && !file->value->data.file.is_std) {
+        fclose(file->value->data.file.file);
+        file->value->data.file.file = NULL;
+        file->value->data.file.is_std = true;
+        memFree(file->value->data.file.path);
+        memFree(file->value->data.file.mode);
+    }
 
-    return_:
     setResult(result, inter);
     return result->type;
 }

+ 106 - 0
VirtulMathCore/ofunc/src/lib_.c

@@ -0,0 +1,106 @@
+#include "__ofunc.h"
+
+ResultType lib_new(O_FUNC){
+    LinkValue *value = NULL;
+    ArgumentParser ap[] = {{.type=only_value, .must=1, .long_arg=false},
+                           {.must=-1}};
+    int status = 1;
+    setResultCore(result);
+    arg = parserValueArgument(ap, arg, &status, NULL);
+    if (status != 1){
+        setResultError(E_ArgumentException, FEW_ARG, LINEFILE, true, CNEXT_NT);
+        return R_error;
+    }
+    value = make_new(inter, belong, ap[0].value);
+    value->value->type = V_lib;
+    value->value->data.lib.handle = NULL;
+
+    run_init(value, arg, LINEFILE, CNEXT_NT);
+    return result->type;
+}
+
+ResultType lib_init(O_FUNC){
+    ArgumentParser ap[] = {{.type=only_value, .must=1, .long_arg=false},
+                           {.type=name_value, .name=L"path", .must=1, .long_arg=false},
+                           {.must=-1}};
+    LinkValue *clib;
+    char *path;
+    void *handle;
+    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) {
+        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(path, str), LINEFILE, true, CNEXT_NT);
+        return R_error;
+    }
+    path = memWcsToStr(ap[1].value->value->data.str.str, false);
+    handle = dlopen(path, RTLD_NOW);
+    if (handle == NULL) {
+        wchar_t *tmp = memWidecat(L"load lib error: ", memStrToWcs(dlerror(), false), false, true);
+        setResultError(E_ImportException, tmp, LINEFILE, true, CNEXT_NT);
+        goto return_;
+    }
+    clib->value->data.lib.handle = handle;
+
+    {
+        void (*test)(void) = dlsym(handle, "init");
+        if (test != NULL)
+            test();
+    }
+
+    setResult(result, inter);
+    return_:
+    memFree(path);
+    return result->type;
+}
+
+ResultType lib_close(O_FUNC){
+    ArgumentParser ap[] = {{.type=only_value, .must=1, .long_arg=false},
+                           {.must=-1}};
+    LinkValue *clib;
+    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) {
+        setResultError(E_TypeException, INSTANCE_ERROR(clib), LINEFILE, true, CNEXT_NT);
+        return R_error;
+    }
+
+    if (clib->value->data.lib.handle != NULL) {
+        dlclose(clib->value->data.lib.handle);
+        clib->value->data.lib.handle = NULL;
+    }
+
+    setResult(result, inter);
+    return result->type;
+}
+
+void registeredLib(R_FUNC){
+    LinkValue *object = inter->data.lib_;
+    NameFunc tmp[] = {{L"close", lib_close, 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_},
+                      {NULL, NULL}};
+    gc_addTmpLink(&object->gc_status);
+    addBaseClassVar(L"clib", object, belong, inter);
+    iterBaseClassFunc(tmp, object, CFUNC_CORE(inter->var_list));
+    gc_freeTmpLink(&object->gc_status);
+}
+
+void makeBaseLib(Inter *inter){
+    LinkValue *lib_ = makeBaseChildClass(inter->data.vobject, inter);
+    gc_addStatementLink(&lib_->gc_status);
+    inter->data.lib_ = lib_;
+}

+ 6 - 0
VirtulMathCore/ofunc/src/vobject.c

@@ -122,6 +122,12 @@ ResultType vobject_bool(O_FUNC){
         case V_dict:
             result_ = value->data.dict.size > 0;
             break;
+        case V_lib:
+            result_ = value->data.lib.handle != NULL;
+            break;
+        case V_file:
+            result_ = value->data.file.file != NULL;
+            break;
         default:
             setResultError(E_TypeException, CUL_ERROR(bool), LINEFILE, true, CNEXT_NT);
             return R_error;

+ 1 - 0
VirtulMathCore/src/inter.c

@@ -98,6 +98,7 @@ void freeBaseInterData(struct Inter *inter){
     gc_freeStatementLink(&inter->data.bool_->gc_status);
     gc_freeStatementLink(&inter->data.function->gc_status);
     gc_freeStatementLink(&inter->data.pass_->gc_status);
+    gc_freeStatementLink(&inter->data.lib_->gc_status);
     gc_freeStatementLink(&inter->data.file->gc_status);
     gc_freeStatementLink(&inter->data.tuple->gc_status);
     gc_freeStatementLink(&inter->data.list->gc_status);

+ 2 - 0
VirtulMathCore/src/ofunc.c

@@ -12,6 +12,7 @@ static Registered base_func_list[] = {registeredVObject,
                                       registeredDictIter,
                                       registeredExcIter,
                                       registeredFile,
+                                      registeredLib,
 
                                       registeredSysFunction,
                                       registeredIOFunction,
@@ -48,6 +49,7 @@ void registeredFunctionName(Inter *inter, LinkValue *belong){
     makeBaseDictIter(inter);
     makeExcIter(inter);
     makeBaseFile(inter);
+    makeBaseLib(inter);
 
     makeBaseStr(inter);
     presetting(inter);

+ 6 - 0
VirtulMathCore/src/value.c

@@ -718,6 +718,12 @@ void printValue(Value *value, FILE *debug, bool print_father, bool print_in) {
         case V_ell:
             fprintf(debug, "...");
             break;
+        case V_lib:
+            if (print_father)
+                fprintf(debug, "lib");
+            else
+                fprintf(debug, "(lib on %p)", value);
+            break;
         default:
             fprintf(debug, "unknown");
             break;