Browse Source

adjusted api so that api user is no longer responsible for freeing
returned strings

Kolten Pearson 2 năm trước cách đây
mục cha
commit
54134bfecb
6 tập tin đã thay đổi với 19 bổ sung13 xóa
  1. 13 2
      c_bindings/pocketpy_c.cpp
  2. 3 4
      c_bindings/pocketpy_c.h
  3. 0 4
      c_bindings/test.c
  4. 1 1
      src/gc.h
  5. 1 1
      src/tuplelist.h
  6. 1 1
      src/vm.h

+ 13 - 2
c_bindings/pocketpy_c.cpp

@@ -36,6 +36,7 @@ using namespace pkpy;
 struct pkpy_vm_wrapper {
     VM* vm;
     ValueStackImpl<PKPY_STACK_SIZE>* c_data;
+    char* string_ret;
 };
 
 
@@ -62,6 +63,13 @@ static void unpack_return(struct pkpy_vm_wrapper* w, PyObject* ret) {
 
 }
 
+static char* manage_string(struct pkpy_vm_wrapper* w, char* s) {
+    if (w->string_ret != NULL)
+        free(w->string_ret);
+    w->string_ret = s;
+    return w->string_ret;
+}
+
 
 bool pkpy_clear_error(struct pkpy_vm_wrapper* w, char** message) {
     SAFEGUARD_OPEN
@@ -72,7 +80,7 @@ bool pkpy_clear_error(struct pkpy_vm_wrapper* w, char** message) {
         w->c_data->pop();
         Exception& e = py_cast<Exception&>(w->vm, w->c_data->top());
         if (message != nullptr) 
-            *message = e.summary().c_str_dup();
+            *message = manage_string(w, e.summary().c_str_dup());
         else
             std::cerr << "ERROR: " << e.summary() << "\n";
 
@@ -88,6 +96,7 @@ struct pkpy_vm_wrapper* pkpy_vm_create(bool use_stdio, bool enable_os) {
     struct pkpy_vm_wrapper* w = (struct pkpy_vm_wrapper*) malloc(sizeof(*w));
     w->vm = new VM(use_stdio, enable_os);
     w->c_data = new ValueStackImpl<PKPY_STACK_SIZE>();
+    w->string_ret = NULL;
 
     return w;
 }
@@ -110,6 +119,8 @@ bool pkpy_vm_run(struct pkpy_vm_wrapper* w, const char* source) {
 void pkpy_vm_destroy(struct pkpy_vm_wrapper* w) {
     delete w->vm;
     delete w->c_data;
+    if (w->string_ret != NULL)
+        free(w->string_ret);
     free(w);
 }
 
@@ -366,7 +377,7 @@ bool pkpy_to_string(struct pkpy_vm_wrapper* w, int index, char** ret) {
     PyObject* o = w->c_data->begin()[index];
     if (ret != nullptr) {
         Str& s = py_cast<Str&>(w->vm, o);
-        *ret = s.c_str_dup();
+        *ret = manage_string(w, s.c_str_dup());
     }
 
     return true;

+ 3 - 4
c_bindings/pocketpy_c.h

@@ -18,9 +18,9 @@ typedef struct pkpy_vm_wrapper pkpy_vm;
 //if pkpy_clear_error returns false it means that no error was set, and it takes no action
 //if pkpy_clear_error returns true it means there was an error and it was cleared, 
 //it will provide a string summary of the error in the message parameter (if it is not NULL)
-//NOTE : you need to free the message that is passed back after you are done using it
-//or else pass in null as message, and it will just print the message to stderr
+//if null is passed in as message, and it will just print the message to stderr
 bool pkpy_clear_error(pkpy_vm*, char** message);
+//the message pointer is only valid until the next api call, so copy it if you want it
 
 pkpy_vm* pkpy_vm_create(bool use_stdio, bool enable_os);
 bool pkpy_vm_run(pkpy_vm*, const char* source);
@@ -60,9 +60,8 @@ bool pkpy_call_method(pkpy_vm*, const char* name, int argc);
 bool pkpy_to_int(pkpy_vm*, int index, int* ret);
 bool pkpy_to_float(pkpy_vm*, int index, double* ret);
 bool pkpy_to_bool(pkpy_vm*, int index, bool* ret);
-//you have to free ret after you are done using it
 bool pkpy_to_string(pkpy_vm*, int index, char** ret);
-
+//the ret string pointer is only valid until the next api call, so copy it if you want it
 
 //these do not follow the same error semantics as above, their return values
 //just say whether the check succeeded or not, or else return the value asked for

+ 0 - 4
c_bindings/test.c

@@ -14,7 +14,6 @@ void check_impl(pkpy_vm* vm, bool result, int lineno) {
         }
 
         printf("%s\n", message);
-        free(message);
         exit(1);
     }
 }
@@ -27,7 +26,6 @@ void fail_impl(pkpy_vm* vm, bool result, int lineno) {
         char* message;
         if (pkpy_clear_error(vm, &message)) {
             printf("actually errored!\n");
-            free(message);
             exit(1);
         }
     }
@@ -44,7 +42,6 @@ void error_impl(pkpy_vm* vm, bool result, int lineno) {
         else {
             printf("successfully errored with this message: \n");
             printf("%s\n", message);
-            free(message);
         }
     }
 }
@@ -146,7 +143,6 @@ int main(int argc, char** argv) {
     fail(pkpy_is_float(vm, -1));
     fail(pkpy_is_bool(vm, -1));
     fail(pkpy_is_none(vm, -1));
-    free(r_string);
 
     printf("\ntesting None methods\n");
     check(pkpy_push_none(vm));

+ 1 - 1
src/gc.h

@@ -116,4 +116,4 @@ inline void FuncDecl::_gc_mark() const{
     for(int i=0; i<kwargs.size(); i++) OBJ_MARK(kwargs[i].value);
 }
 
-}   // namespace pkpy
+}   // namespace pkpy

+ 1 - 1
src/tuplelist.h

@@ -93,4 +93,4 @@ struct ArgsView{
         return ret;
     }
 };
-}   // namespace pkpy
+}   // namespace pkpy

+ 1 - 1
src/vm.h

@@ -1203,4 +1203,4 @@ inline Str obj_type_name(VM *vm, Type type){
 #undef PY_VAR_INT
 #undef PY_VAR_FLOAT
 
-}   // namespace pkpy
+}   // namespace pkpy