瀏覽代碼

feat: C函数形参增加指针类型和宽字符类型

SongZihuan 4 年之前
父節點
當前提交
ee72387a2c

+ 1 - 1
VirtulMathCore/include/inter.h

@@ -36,6 +36,7 @@ struct Inter{
         struct LinkValue *none;
         struct LinkValue *list_iter;
         struct LinkValue *dict_iter;
+        struct LinkValue *pointer;
 
         struct LinkValue *base_exc;
         struct LinkValue *sys_exc;
@@ -60,7 +61,6 @@ struct Inter{
 
         wchar_t *var_str_prefix;
         wchar_t *var_int_prefix;
-        wchar_t *var_dou_prefix;
         wchar_t *var_bool_prefix;
         wchar_t *var_file_prefix;
         wchar_t *var_none;

+ 1 - 0
VirtulMathCore/include/ofunc.h

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

+ 2 - 0
VirtulMathCore/include/parameter.h

@@ -69,11 +69,13 @@ struct ArgumentFFI {
         af_ldouble,
 
         af_str,
+        af_wstr,
 
         af_uchar,
         af_char,
 
         af_void,
+        af_pointer,
     } *type;  // 数据类型 (决定如何释放arg_v)
     unsigned int size;  // 数组长度
 };

+ 7 - 0
VirtulMathCore/include/value.h

@@ -51,6 +51,7 @@ enum ValueType {
     V_ell=10,
     V_file=11,
     V_lib=12,
+    V_pointer=13,
 };
 
 struct Int {
@@ -122,6 +123,10 @@ struct File{
     bool is_std;
 };
 
+struct Pointer {
+    void *pointer;
+};
+
 struct Value{
     enum ValueType type;
 
@@ -141,6 +146,7 @@ struct Value{
         struct Bool bool_;
         struct File file;
         struct Lib lib;
+        struct Pointer pointer;
     } data;
 
     struct Value *gc_next;
@@ -230,6 +236,7 @@ Value *makeBoolValue(bool bool_num, fline line, char *file, FUNC_NT);
 Value *makePassValue(fline line, char *file, FUNC_NT);
 Value *makeIntValue(vint num, fline line, char *file, FUNC_NT);
 Value *makeDouValue(vdou num, fline line, char *file, FUNC_NT);
+Value *makePointerValue(void *p, fline line, char *file, FUNC_NT);
 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);

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

@@ -0,0 +1,5 @@
+#ifndef VIRTUALMATH_POINTER_H
+#define VIRTUALMATH_POINTER_H
+void registeredPointer(R_FUNC);
+void makeBasePointer(Inter *inter);
+#endif //VIRTUALMATH_POINTER_H

+ 3 - 0
VirtulMathCore/ofunc/src/dou.c

@@ -37,6 +37,9 @@ ResultType dou_init(O_FUNC){
         case V_int:
             base->value->data.dou.num = (vdou)ap[1].value->value->data.int_.num;
             break;
+        case V_pointer:
+            base->value->data.dou.num = (vdou)(vint)(ap[1].value->value->data.pointer.pointer);  // 需要两次转换
+            break;
         case V_dou:
             base->value->data.dou.num = ap[1].value->value->data.dou.num;
             break;

+ 3 - 0
VirtulMathCore/ofunc/src/int.c

@@ -37,6 +37,9 @@ ResultType int_init(O_FUNC){
         case V_int:
             base->value->data.int_.num = ap[1].value->value->data.int_.num;
             break;
+        case V_pointer:
+            base->value->data.int_.num = (vint)ap[1].value->value->data.pointer.pointer;
+            break;
         case V_dou:
             base->value->data.int_.num = (vint)ap[1].value->value->data.dou.num;
             break;

+ 69 - 0
VirtulMathCore/ofunc/src/pointer.c

@@ -0,0 +1,69 @@
+#include "__ofunc.h"
+
+ResultType pointer_new(O_FUNC){
+    LinkValue *value = NULL;
+    ArgumentParser ap[] = {{.type=only_value, .must=1, .long_arg=false},
+                           {.must=-1}};
+    int status = 1;
+    arg = parserValueArgument(ap, arg, &status, NULL);
+    if (status != 1){
+        setResultError(E_ArgumentException, FEW_ARG, LINEFILE, true, CNEXT_NT);
+        return R_error;
+    }
+
+    setResultCore(result);
+    value = make_new(inter, belong, ap[0].value);
+    value->value->type = V_pointer;
+    value->value->data.pointer.pointer = NULL;
+    run_init(value, arg, LINEFILE, CNEXT_NT);
+    return result->type;
+}
+
+ResultType pointer_init(O_FUNC){
+    ArgumentParser ap[] = {{.type=only_value, .must=1, .long_arg=false},
+                           {.type=name_value, .name=L"p", .must=0, .long_arg=false},
+                           {.must=-1}};
+    LinkValue *base = NULL;
+    setResultCore(result);
+    parserArgumentUnion(ap, arg, CNEXT_NT);
+    if (!CHECK_RESULT(result))
+        return result->type;
+    freeResult(result);
+
+    base = ap[0].value;
+    if (ap[1].value == NULL)
+        goto return_;
+    switch (ap[1].value->value->type){
+        case V_int:
+            base->value->data.pointer.pointer = (void *)ap[1].value->value->data.int_.num;
+            break;
+        case V_none:
+        case V_ell:
+            base->value->data.pointer.pointer = NULL;
+            break;
+        default:
+            setResultError(E_TypeException, ERROR_INIT(num), LINEFILE, true, CNEXT_NT);
+            return result->type;
+    }
+
+    return_:
+    setResultBase(result, inter);
+    return result->type;
+}
+
+void registeredPointer(R_FUNC){
+    LinkValue *object = inter->data.pointer;
+    NameFunc tmp[] = {{inter->data.object_new, pointer_new, class_free_},
+                      {inter->data.object_init, pointer_init, object_free_},
+                      {NULL, NULL}};
+    gc_addTmpLink(&object->gc_status);
+    addBaseClassVar(L"pointer", object, belong, inter);
+    iterBaseClassFunc(tmp, object, CFUNC_CORE(inter->var_list));
+    gc_freeTmpLink(&object->gc_status);
+}
+
+void makeBasePointer(Inter *inter){
+    LinkValue *pointer = makeBaseChildClass(inter->data.vobject, inter);
+    gc_addStatementLink(&pointer->gc_status);
+    inter->data.pointer = pointer;
+}

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

@@ -130,6 +130,9 @@ ResultType vobject_bool(O_FUNC){
         case V_dou:
             result_ = value->data.dou.num != 0;
             break;
+        case V_pointer:
+            result_ = value->data.pointer.pointer != NULL;
+            break;
         case V_str:
             result_ = memWidelen(value->data.str.str) > 0;
             break;
@@ -179,6 +182,12 @@ ResultType vobject_repo(O_FUNC){
             repo = memStrToWcs(str, false);
             break;
         }
+        case V_pointer: {
+            char str[30] = { NUL };
+            snprintf(str, 30, "%p", value->data.pointer.pointer);
+            repo = memStrToWcs(str, false);
+            break;
+        }
         case V_dou: {
             char str[30] = { NUL };
             if (value->data.dou.num != 0)

+ 9 - 1
VirtulMathCore/src/__run.c

@@ -74,7 +74,13 @@ wchar_t *setIntVarName(vint num, struct Inter *inter) {
 wchar_t *setDouVarName(vdou num, struct Inter *inter) {
     wchar_t name[50];
     swprintf(name, 50, L"%Lf", num);
-    return memWidecat(inter->data.var_dou_prefix, name, false, false);
+    return memWidecat(inter->data.var_int_prefix, name, false, false);
+}
+
+wchar_t *setPointerVarName(void *num, struct Inter *inter) {
+    wchar_t name[50];
+    swprintf(name, 50, L"%p", num);
+    return memWidecat(inter->data.var_int_prefix, name, false, false);
 }
 
 wchar_t *getNameFromValue(Value *value, struct Inter *inter) {
@@ -85,6 +91,8 @@ wchar_t *getNameFromValue(Value *value, struct Inter *inter) {
             return setIntVarName(value->data.int_.num, inter);
         case V_dou:
             return setDouVarName(value->data.dou.num, inter);
+        case V_pointer:
+            return setPointerVarName(value->data.pointer.pointer, inter);
         case V_bool:
             if (value->data.bool_.bool_)
                 return memWidecat(inter->data.var_bool_prefix, L"true", false, false);

+ 2 - 3
VirtulMathCore/src/inter.c

@@ -54,8 +54,7 @@ Inter *makeInter(char *out, char *error_, char *in, LinkValue *belong) {
 
 void setBaseInterData(struct Inter *inter){
     inter->data.var_str_prefix = setName("str_");
-    inter->data.var_int_prefix = setName("int_");
-    inter->data.var_dou_prefix = setName("double_");
+    inter->data.var_int_prefix = setName("num_");
     inter->data.var_file_prefix = setName("file_");
     inter->data.var_none = setName("none");
     inter->data.var_pass = setName("ellipsis");
@@ -97,6 +96,7 @@ void freeBaseInterData(struct Inter *inter){
     gc_freeStatementLink(&inter->data.vobject->gc_status);
     gc_freeStatementLink(&inter->data.int_->gc_status);
     gc_freeStatementLink(&inter->data.dou->gc_status);
+    gc_freeStatementLink(&inter->data.pointer->gc_status);
     gc_freeStatementLink(&inter->data.str->gc_status);
     gc_freeStatementLink(&inter->data.bool_->gc_status);
     gc_freeStatementLink(&inter->data.function->gc_status);
@@ -134,7 +134,6 @@ void freeBaseInterData(struct Inter *inter){
     gc_freeStatementLink(&inter->data.include_exp->gc_status);
 
     memFree(inter->data.var_int_prefix);
-    memFree(inter->data.var_dou_prefix);
     memFree(inter->data.var_str_prefix);
     memFree(inter->data.var_file_prefix);
     memFree(inter->data.var_object_prefix);

+ 2 - 0
VirtulMathCore/src/ofunc.c

@@ -14,6 +14,7 @@ static Registered base_func_list[] = {registeredVObject,
                                       registeredExcIter,
                                       registeredFile,
                                       registeredLib,
+                                      registeredPointer,
 
                                       registeredSysFunction,
                                       registeredIOFunction,
@@ -52,6 +53,7 @@ void registeredFunctionName(Inter *inter, LinkValue *belong){
     makeExcIter(inter);
     makeBaseFile(inter);
     makeBaseLib(inter);
+    makeBasePointer(inter);
 
     makeBaseStr(inter);
     presetting(inter);

+ 46 - 7
VirtulMathCore/src/parameter.c

@@ -878,18 +878,17 @@ void setArgumentFFI(ArgumentFFI *af, unsigned int size) {
 
 void freeArgumentFFI(ArgumentFFI *af) {
     for (unsigned int i=0; i < af->size; i++) {
-        switch (af->type[i]) {
-            case af_double:
-            case af_int:
-            case af_char:
-                memFree(af->arg_v[i]);
-                break;
+        switch (af->type[i]) {  // TODO-szh 改为if-else分支
+            case af_wstr:
             case af_str:
                 if (af->arg_v[i] != NULL)
-                    memFree(*(char **)af->arg_v[i]);
+                    memFree(*(void **)af->arg_v[i]);
                 memFree(af->arg_v[i]);
                 break;
+            case af_void:
+                break;
             default:
+                memFree(af->arg_v[i]);
                 break;
         }
     }
@@ -935,6 +934,9 @@ static bool setFFIArgFromValue(ArgumentFFI *af, Argument *arg, unsigned int i) {
         setFFIValue(V_dou, ffi_type_double, af_double, double, arg->data.value->value->data.dou.num);
         setFFIValue(V_bool, ffi_type_sint32, af_int, double, arg->data.value->value->data.bool_.bool_);
         setFFIValue(V_str, ffi_type_pointer, af_str, char *, memWcsToStr(arg->data.value->value->data.str.str, false));
+        setFFIValue(V_pointer, ffi_type_void, af_int, void *, arg->data.value->value->data.pointer.pointer);
+
+        case V_ell:
         setFFIValue(V_none, ffi_type_sint32, af_int, int, 0);
         default:
             return false;
@@ -954,12 +956,16 @@ case aft_type: \
         case V_dou: \
             *(type_ *)(af->arg_v[i]) = (type_)arg->data.value->value->data.dou.num; \
             break; \
+        case V_ell: \
         case V_none: \
             *(type_ *)(af->arg_v[i]) = (type_)0; \
             break; \
         case V_bool: \
             *(type_ *)(af->arg_v[i]) = (type_)arg->data.value->value->data.bool_.bool_; \
             break; \
+        case V_pointer: \
+            *(type_ *)(af->arg_v[i]) = (type_)(vint)arg->data.value->value->data.pointer.pointer; \
+            break; \
         default: \
             return false; \
     } } while(0); \
@@ -986,6 +992,24 @@ static bool setFFIArgFromType(ArgumentFFI *af, Argument *arg, unsigned int i) {
         setFFIArgFromTypeNumber(af_ldouble, long double);
         setFFIArgFromTypeNumber(af_double, double);
 
+        case af_pointer:
+            af->arg_v[i] = memCalloc(1, sizeof(void *));
+            switch (arg->data.value->value->type) {
+                case V_int:
+                    *(void **) (af->arg_v[i]) = (void *) arg->data.value->value->data.int_.num;
+                    break;
+                case V_ell:
+                case V_none:
+                    *(void **) (af->arg_v[i]) = NULL;
+                    break;
+                case V_pointer:
+                    *(void **) (af->arg_v[i]) = (void *)arg->data.value->value->data.pointer.pointer;
+                    break;
+                default:
+                    return 0;
+            }
+        break;
+
         setFFIArgFromTypeChar(af_char, int8_t);
         setFFIArgFromTypeChar(af_uchar, u_int8_t);
 
@@ -996,6 +1020,15 @@ static bool setFFIArgFromType(ArgumentFFI *af, Argument *arg, unsigned int i) {
             } else
                 return false;
             break;
+
+        case af_wstr:
+            af->arg_v[i] = memCalloc(1, sizeof(wchar_t *));  // af->arg_v是ffi_type **arg_v, 即 *arg_v[]
+            if (arg->data.value->value->type == V_str) {
+                *(wchar_t **)(af->arg_v[i]) = memWidecpy(arg->data.value->value->data.str.str);
+            } else
+                return false;
+            break;
+
         default:
             return false;
     }
@@ -1046,12 +1079,18 @@ ffi_type *getFFIType(wchar_t *str, enum ArgumentFFIType *aft) {\
     } else if (eqWide(str, L"str")) {
         return_ = &ffi_type_pointer;
         *aft = af_str;
+    } else if (eqWide(str, L"wstr")) {
+        return_ = &ffi_type_pointer;
+        *aft = af_wstr;
     } else if (eqWide(str, L"char")) {
         return_ = &ffi_type_schar;
         *aft = af_char;
     } else if (eqWide(str, L"void")) {
         return_ = &ffi_type_void;
         *aft = af_void;
+    } else if (eqWide(str, L"pointer")) {
+        return_ = &ffi_type_pointer;
+        *aft = af_pointer;
     }
     return return_;
 }

+ 25 - 1
VirtulMathCore/src/runcall.c

@@ -261,15 +261,28 @@ static ResultType callCFunction(LinkValue *function_value, Argument *arg, long i
 static bool makeFFIReturn(enum ArgumentFFIType af, void **re_v) {
     switch (af) {
         case af_char:
+        case af_uchar:
+        case af_usint:
+        case af_sint:
+        case af_uint:
         case af_int:
+        case af_ulint:
+        case af_lint:
             *re_v = memCalloc(1, sizeof(int64_t));  // 无论是int32或者是int64,都申请int64_t的内存 (否则libffi会提升类型,导致内存溢出)
             break;
+
+        case af_float:
+        case af_ldouble:
         case af_double:
             *re_v = memCalloc(1, sizeof(long double));  // 理由同上
             break;
+
+        case af_pointer:
         case af_str:
+        case af_wstr:
             *re_v = memCalloc(1, sizeof(void *));  // 所有指针数据大小都相同
             break;
+
         case af_void:
             *re_v = NULL;
             break;
@@ -297,12 +310,23 @@ static bool FFIReturnValue(enum ArgumentFFIType aft, void *re_v, fline line, cha
             break;
 
         case af_str: {
-            wchar_t *tmp = memStrToWcs(re_v, false);
+            wchar_t *tmp = memStrToWcs(*(char **)re_v, false);
             makeStringValue(tmp, line, file, CNEXT_NT);
             memFree(tmp);
             break;
         }
 
+        case af_wstr: {
+            wchar_t *tmp = memWidecpy(*(wchar_t **)re_v);
+            makeStringValue(tmp, line, file, CNEXT_NT);
+            memFree(tmp);
+            break;
+        }
+
+        case af_pointer:
+            makePointerValue(*(void **)re_v, line, file, CNEXT_NT);
+            break;
+
         case af_uchar:
         case af_char: {
             wchar_t tmp[] = {(wchar_t)(*(int64_t *)re_v), WNUL};

+ 11 - 0
VirtulMathCore/src/value.c

@@ -87,6 +87,17 @@ Value *makeDouValue(vdou num, fline line, char *file, FUNC_NT) {
     return tmp;
 }
 
+Value *makePointerValue(void *p, fline line, char *file, FUNC_NT) {
+    Value *tmp = NULL;
+    setResultCore(result);
+    callBackCore(inter->data.pointer, NULL, line, file, 0, CNEXT_NT);
+    if (!CHECK_RESULT(result))
+        return NULL;
+    tmp = result->value->value;
+    tmp->data.pointer.pointer = p;
+    return tmp;
+}
+
 Value *makeStringValue(wchar_t *str, fline line, char *file, FUNC_NT) {
     Value *tmp = NULL;
     setResultCore(result);