From b251a089cb01dc262ac3c0d41cdcf17da3b0ae3c Mon Sep 17 00:00:00 2001
From: David Hendriks <davidhendriks93@gmail.com>
Date: Fri, 17 Jan 2020 14:26:48 +0000
Subject: [PATCH] added general run_system api binding, which will eventually
 replace the individual ones. this function runs a system, and depending on
 the input it will use a custom logging, a preloaded store, write log to file
 etc. I think it will be better to just write some if statements in a single
 function, and not have too many repeating code

---
 include/binary_c_python.h |   9 ++--
 src/binary_c_python.c     |  50 ++++++++++++++++++
 src/binary_c_python_api.c | 104 +++++++++++++++++++++++++++++++++-----
 3 files changed, 146 insertions(+), 17 deletions(-)

diff --git a/include/binary_c_python.h b/include/binary_c_python.h
index fe229b9b2..ee7544c26 100644
--- a/include/binary_c_python.h
+++ b/include/binary_c_python.h
@@ -9,9 +9,6 @@
 #include "binary_c_API_prototypes.h"
 
 /* Binary_c's python API prototypes */
-
-
-
 int run_binary(char * argstring,
                 char ** const outstring,
                 char ** const errorstring,
@@ -35,6 +32,12 @@ int run_population(char * argstring,
                char ** const error_buffer,
                size_t * const nbytes);
 
+int run_system(char * argstring,
+               long int custom_logging_func_memaddr,
+               long int store_memaddr,
+               char ** const buffer,
+               char ** const error_buffer,
+               size_t * const nbytes);
 
 /* =================================================================== */
 /* Functions to call other API functionality like help and arglines    */
diff --git a/src/binary_c_python.c b/src/binary_c_python.c
index 1c9d589fe..c9a3876d1 100644
--- a/src/binary_c_python.c
+++ b/src/binary_c_python.c
@@ -43,6 +43,8 @@ static char run_binary_custom_logging_docstring[] =
     "TODO";
 static char run_population_docstring[] = 
     "Run population of systems";
+static char run_system_docstring[] = 
+    "Function to run a system. This is a general function that will be able to handle different kinds of situations: single system run with different settings, population run with different settings, etc. To avoid having too many functions doing slightly different things.";
 
 // Utility function docstrings
 static char return_arglines_docstring[] =
@@ -73,6 +75,7 @@ static PyObject* binary_c_run_binary(PyObject *self, PyObject *args);
 static PyObject* binary_c_run_binary_with_logfile(PyObject *self, PyObject *args);
 static PyObject* binary_c_run_binary_custom_logging(PyObject *self, PyObject *args);
 static PyObject* binary_c_run_population(PyObject *self, PyObject *args);
+static PyObject* binary_c_run_system(PyObject *self, PyObject *args);
 
 // Utility function headers
 static PyObject* binary_c_return_arglines(PyObject *self, PyObject *args);
@@ -105,6 +108,9 @@ static PyMethodDef module_methods[] = {
     {"run_binary_with_logfile", binary_c_run_binary_with_logfile, METH_VARARGS, run_binary_with_log_docstring},
     {"run_binary_custom_logging", binary_c_run_binary_custom_logging, METH_VARARGS, run_binary_custom_logging_docstring},
     {"run_population", binary_c_run_population, METH_VARARGS, run_population_docstring},
+    {"run_system", binary_c_run_system, METH_VARARGS, run_system_docstring},
+
+
 
     {"return_arglines", binary_c_return_arglines, METH_VARARGS, return_arglines_docstring},
     {"return_help", binary_c_return_help_info, METH_VARARGS, return_help_info_docstring},
@@ -396,6 +402,50 @@ static PyObject* binary_c_run_population(PyObject *self, PyObject *args)
     return return_string;
 }
 
+static PyObject* binary_c_run_system(PyObject *self, PyObject *args)
+{
+    /* Parse the input tuple */
+    char *argstring;
+    long int custom_logging_func_memaddr;
+    long int store_memaddr;
+
+    if(!PyArg_ParseTuple(args, "sll", &argstring, &custom_logging_func_memaddr, &store_memaddr))
+    {
+        return NULL;
+    }
+
+    char * buffer;
+    char * error_buffer;
+    size_t nbytes;
+    int out MAYBE_UNUSED = run_system(argstring,
+                                      custom_logging_func_memaddr, 
+                                      store_memaddr,
+                                      &buffer,
+                                      &error_buffer,
+                                      &nbytes);
+
+    /* copy the buffer to a python string */
+    PyObject * return_string = Py_BuildValue("s", buffer);
+    PyObject * return_error_string MAYBE_UNUSED = Py_BuildValue("s", error_buffer);
+
+    if(error_buffer != NULL && strlen(error_buffer)>0)
+    {
+        fprintf(stderr,
+                "Error in binary_c run : %s\n",
+                error_buffer);
+    }
+    
+    Safe_free(buffer);
+    Safe_free(error_buffer);
+
+    /* 
+     * TODO
+     * return the return_error_string as well!
+     */
+    return return_string;
+}
+
+
 
 /* ============================================================================== */
 /* Wrappers to functions that call other API functionality like help and arglines */
diff --git a/src/binary_c_python_api.c b/src/binary_c_python_api.c
index 603f89d5c..68be4e74c 100644
--- a/src/binary_c_python_api.c
+++ b/src/binary_c_python_api.c
@@ -5,6 +5,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <stdint.h>
+
 
 
 /*
@@ -227,13 +229,8 @@ int run_population(char * argstring,
     /* memory for N binary systems */
     struct libbinary_c_stardata_t *stardata;
 
-    // load the store
-    // struct libbinary_c_store_t * store = (void*)store_memaddr;
+    // load the store from the integer that has been passed
     struct libbinary_c_store_t * store = (void*)store_memaddr;
-    // struct libbinary_c_store_t * store = (void*)(struct stardata_t *)custom_logging_func_memaddr;
-    // struct libbinary_c_store_t * store = (void*)(struct stardata_t *)custom_logging_func_memaddr;
-    // struct libbinary_c_store_t * store = (void*)(struct stardata_t *)custom_logging_func_memaddr;
-    // struct libbinary_c_store_t * store = NULL;
 
     /* make new stardata */
     stardata = NULL;
@@ -257,7 +254,12 @@ int run_population(char * argstring,
     /* output to strings */
     stardata->preferences->internal_buffering = INTERNAL_BUFFERING_STORE;
     stardata->preferences->batchmode = BATCHMODE_LIBRARY;
-    // stardata->preferences->custom_output_function = (void*)(struct stardata_t *)custom_logging_func_memaddr;
+
+    /* Check the value of the custom_logging_memaddr */
+    if(custom_logging_func_memaddr != -1)
+    {
+        stardata->preferences->custom_output_function = (void*)(struct stardata_t *)custom_logging_func_memaddr;
+    }
 
     /* do binary evolution */
     binary_c_evolve_for_dt(stardata,
@@ -275,11 +277,87 @@ int run_population(char * argstring,
     /* free stardata (except the buffer) */
     binary_c_free_memory(&stardata,TRUE,TRUE,FALSE,FALSE);
         
-    // Ask rob whether to free the memory here or not? or to free it manually.
+    // TODO: Ask rob whether to free the memory here or not? or to free it manually.
+    return 0;
+}
+
+
+// This one will replace the different ones above. needs to handle multiple input choices and decide what to do.
+int run_system(char * argstring,
+               long int custom_logging_func_memaddr,
+               long int store_memaddr,
+               char ** const buffer,
+               char ** const error_buffer,
+               size_t * const nbytes)
+{
+    /* memory for N binary systems */
+    struct libbinary_c_stardata_t *stardata;
+
+    // Store:
+    /* Check the value of the store_memaddr */
+    struct libbinary_c_store_t * store;
+    if(store_memaddr != -1)
+    {
+        // load the store from the integer that has been passed
+        // struct libbinary_c_store_t * store = (void*)store_memaddr;
+        store = (void*)store_memaddr;
+    }
+    else
+    {
+        // struct libbinary_c_store_t * store = NULL;
+        store = NULL;
+    }
+
+    /* make new stardata */
+    stardata = NULL;
+    binary_c_new_system(&stardata,
+                        NULL,
+                        NULL,
+                        &store,
+                        &argstring,
+                        -1);
+    
+    /* disable logging */
+    snprintf(stardata->preferences->log_filename,
+             STRING_LENGTH-1,
+             "%s",
+             "/dev/null");
+    snprintf(stardata->preferences->api_log_filename_prefix,
+             STRING_LENGTH-1,
+             "%s",
+             "/dev/null");
+
+    /* output to strings */
+    stardata->preferences->internal_buffering = INTERNAL_BUFFERING_STORE;
+    stardata->preferences->batchmode = BATCHMODE_LIBRARY;
+
+    /* Check the value of the custom_logging_memaddr */
+    if(custom_logging_func_memaddr != -1)
+    {
+        stardata->preferences->custom_output_function = (void*)(struct stardata_t *)custom_logging_func_memaddr;
+    }
 
+    /* do binary evolution */
+    binary_c_evolve_for_dt(stardata,
+                           stardata->model.max_evolution_time);
+        
+    /* get buffer pointer */
+    binary_c_buffer_info(stardata,buffer,nbytes);
+    
+    /* get error buffer pointer */
+    binary_c_error_buffer(stardata,error_buffer);
+    
+    /* set raw_buffer_size = -1 to prevent it being freed */
+    stardata->tmpstore->raw_buffer_size = -1;
+    
+    /* free stardata (except the buffer) */
+    binary_c_free_memory(&stardata,TRUE,TRUE,FALSE,FALSE); // CHeck if this is good for single runs.. TODO: 
+        
+    // TODO: Ask rob whether to free the memory here or not? or to free it manually.
     return 0;
 }
 
+
 /* =================================================================== */
 /* Functions to call other API functionality like help and arglines    */
 /* =================================================================== */
@@ -495,11 +573,9 @@ long int return_store(char * argstring,
     /* free stardata (except the buffer) */
     binary_c_free_memory(&stardata, TRUE, TRUE, FALSE, FALSE);
 
-    // int store_ptr;
-    // store_ptr = (void *)store; 
-
+    /* convert the pointer */ 
+    uintptr_t store_memaddr_int = (uintptr_t)store; // C Version converting ptr to int
 
-    // binary_c_free_store_contents(store);
-    // return store_ptr;
-    return store;
+    /* Return the memaddr as an int */
+    return store_memaddr_int;
 }
\ No newline at end of file
-- 
GitLab