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

returned strings
This commit is contained in:
Kolten Pearson 2023-05-01 23:26:55 -06:00
parent 87a76936d6
commit 54134bfecb
6 changed files with 19 additions and 13 deletions

View File

@ -36,6 +36,7 @@ using namespace pkpy;
struct pkpy_vm_wrapper { struct pkpy_vm_wrapper {
VM* vm; VM* vm;
ValueStackImpl<PKPY_STACK_SIZE>* c_data; 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) { bool pkpy_clear_error(struct pkpy_vm_wrapper* w, char** message) {
SAFEGUARD_OPEN SAFEGUARD_OPEN
@ -72,7 +80,7 @@ bool pkpy_clear_error(struct pkpy_vm_wrapper* w, char** message) {
w->c_data->pop(); w->c_data->pop();
Exception& e = py_cast<Exception&>(w->vm, w->c_data->top()); Exception& e = py_cast<Exception&>(w->vm, w->c_data->top());
if (message != nullptr) if (message != nullptr)
*message = e.summary().c_str_dup(); *message = manage_string(w, e.summary().c_str_dup());
else else
std::cerr << "ERROR: " << e.summary() << "\n"; 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)); struct pkpy_vm_wrapper* w = (struct pkpy_vm_wrapper*) malloc(sizeof(*w));
w->vm = new VM(use_stdio, enable_os); w->vm = new VM(use_stdio, enable_os);
w->c_data = new ValueStackImpl<PKPY_STACK_SIZE>(); w->c_data = new ValueStackImpl<PKPY_STACK_SIZE>();
w->string_ret = NULL;
return w; 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) { void pkpy_vm_destroy(struct pkpy_vm_wrapper* w) {
delete w->vm; delete w->vm;
delete w->c_data; delete w->c_data;
if (w->string_ret != NULL)
free(w->string_ret);
free(w); 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]; PyObject* o = w->c_data->begin()[index];
if (ret != nullptr) { if (ret != nullptr) {
Str& s = py_cast<Str&>(w->vm, o); Str& s = py_cast<Str&>(w->vm, o);
*ret = s.c_str_dup(); *ret = manage_string(w, s.c_str_dup());
} }
return true; return true;

View File

@ -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 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, //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) //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 //if null is passed in as message, and it will just print the message to stderr
//or else pass in null as message, and it will just print the message to stderr
bool pkpy_clear_error(pkpy_vm*, char** message); 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); pkpy_vm* pkpy_vm_create(bool use_stdio, bool enable_os);
bool pkpy_vm_run(pkpy_vm*, const char* source); 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_int(pkpy_vm*, int index, int* ret);
bool pkpy_to_float(pkpy_vm*, int index, double* ret); bool pkpy_to_float(pkpy_vm*, int index, double* ret);
bool pkpy_to_bool(pkpy_vm*, int index, bool* 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); 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 //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 //just say whether the check succeeded or not, or else return the value asked for

View File

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