Newer
Older
#include <Python.h>
#include "binary_c_python.h"
/*
* binary_c/PYTHON API interface functions
*
* Remember: variables must be passed by references
* (i.e. as pointers).
*
* See apitest.py for an example of how to use these functions.
*
* See also
* http://www-h.eng.cam.ac.uk/help/tpl/languages/mixinglanguages.html
David Hendriks
committed
* https://realpython.com/build-python-c-extension-module/
* https://docs.python.org/3/extending/extending.html
* https://docs.python.org/3/c-api/arg.html#c.PyArg_ParseTuple
* https://realpython.com/python-bindings-overview/
* http://scipy-lectures.org/advanced/interfacing_with_c/interfacing_with_c.html
*/
/* list of variables used in the Py<>C interface */
/************************************************************/
/*
* function prototypes : these are the functions
* called by PYTHON code, without the trailing underscore.
*/
/************************************************************/
David Hendriks
committed
/* Preparing all the functions of the module */
static char module_docstring[] MAYBE_UNUSED =
"This module is a python3 wrapper around binary_c";
David Hendriks
committed
#ifdef __DEPRECATED
static char create_binary_docstring[] =
"Allocate memory for a binary";
#endif
static char function_prototype_docstring[] =
"The prototype for a binary_c python function";
static char new_binary_system_docstring[] =
"Return an object containing a binary, ready for evolution";
// Evolution function docstrings
static char run_system_docstring[] =
David Hendriks
committed
"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. \n\nArguments:\n\targstring: argument string for binary_c\n\t(opt) custom_logging_func_memaddr: memory address value for custom logging function. Default = -1 (None)\n\t(opt) store_memaddr: memory adress of the store. Default = -1 (None)\n\t(opt) write_logfile: Boolean (in int form) for whether to enable the writing of the log function. Default = 0\n\t(opt) population: Boolean (in int form) for whether this system is part of a population run. Default = 0.";
// Utility function docstrings
static char return_arglines_docstring[] =
"Return the default args for a binary_c system";
static char return_help_info_docstring[] =
"Return the help info for a given parameter";
static char return_help_all_info_docstring[] =
"Return an overview of all the parameters, their description, categorized in sections";
David Hendriks
committed
static char return_version_info_docstring[] =
"Return the version information of the used binary_c build";
// other functionality
static char return_store_memaddr_docstring[] =
"Return the store memory adress that will be passed to run_population";
static char return_persistent_data_memaddr_docstring[] =
David Hendriks
committed
"Return the store memory adress that will be passed to run_population";
static char free_persistent_data_memaddr_and_return_json_output_docstring[] =
"Frees the persistent_data memory and returns the json output";
David Hendriks
committed
static struct libbinary_c_store_t *store = NULL;
David Hendriks
committed
/* Initialize pyobjects */
// Old functions. Can be removed I think
#ifdef __DEPRECATED
static PyObject* binary_c_create_binary(PyObject *self, PyObject *args);
#endif
static PyObject* binary_c_function_prototype(PyObject *self, PyObject *args);
static PyObject* binary_c_new_binary_system(PyObject *self, PyObject *args);
// Evolution function headers
David Hendriks
committed
static PyObject* binary_c_run_system(PyObject *self, PyObject *args, PyObject *kwargs);
// Utility function headers
static PyObject* binary_c_return_arglines(PyObject *self, PyObject *args);
static PyObject* binary_c_return_help_info(PyObject *self, PyObject *args);
static PyObject* binary_c_return_help_all_info(PyObject *self, PyObject *args);
David Hendriks
committed
static PyObject* binary_c_return_version_info(PyObject *self, PyObject *args);
// Other function headers
static PyObject* binary_c_return_store_memaddr(PyObject *self, PyObject *args);
static PyObject* binary_c_return_persistent_data_memaddr(PyObject *self, PyObject *args);
// Free functions
static PyObject* binary_c_free_persistent_data_memaddr_and_return_json_output(PyObject *self, PyObject *args);
David Hendriks
committed
/* Set the module functions */
static PyMethodDef module_methods[] = {
#ifdef __DEPRECATED
{"create_binary",
binary_c_create_binary,
METH_VARARGS,
create_binary_docstring
},
#endif
{"function_prototype", binary_c_function_prototype, METH_VARARGS, function_prototype_docstring},
{"new_system", binary_c_new_binary_system, METH_VARARGS, new_binary_system_docstring},
David Hendriks
committed
{"run_system", (PyCFunction)binary_c_run_system, METH_VARARGS|METH_KEYWORDS, run_system_docstring},
// Wierdly, this casting to a PyCFunction, which usually takes only 2 args, now works when giving keywords. See https://stackoverflow.com/q/10264080
{"return_arglines", binary_c_return_arglines, METH_VARARGS, return_arglines_docstring},
{"return_help", binary_c_return_help_info, METH_VARARGS, return_help_info_docstring},
{"return_help_all", binary_c_return_help_all_info, METH_VARARGS, return_help_all_info_docstring},
David Hendriks
committed
{"return_version_info", binary_c_return_version_info, METH_VARARGS, return_version_info_docstring},
{"return_store_memaddr", binary_c_return_store_memaddr, METH_VARARGS, return_store_memaddr_docstring},
{"return_persistent_data_memaddr", binary_c_return_persistent_data_memaddr, METH_NOARGS, return_persistent_data_memaddr_docstring},
{"free_persistent_data_memaddr_and_return_json_output", binary_c_free_persistent_data_memaddr_and_return_json_output, METH_VARARGS, free_persistent_data_memaddr_and_return_json_output_docstring},
David Hendriks
committed
{NULL, NULL, 0, NULL}
};
David Hendriks
committed
/* ============================================================================== */
/* Making the module */
/* ============================================================================== */
David Hendriks
committed
/* Initialise the module. Removed the part which supports python 2 here on 17-03-2020 */
/* Python 3+ */
David Hendriks
committed
static struct PyModuleDef Py_binary_c_python_api =
{
PyModuleDef_HEAD_INIT,
"binary_c_python_api", /* name of module */
"binary_c_python_api docs", /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
module_methods
};
David Hendriks
committed
PyMODINIT_FUNC PyInit_binary_c_python_api(void)
{
David Hendriks
committed
return PyModule_Create(&Py_binary_c_python_api);
}
David Hendriks
committed
/* ============================================================================== */
David Hendriks
committed
/* Some function that we started out with. Unused now. */
David Hendriks
committed
/* ============================================================================== */
#ifdef __DEPRECATED
static PyObject* binary_c_create_binary(PyObject *self, PyObject *args)
{
double var1, var2;
char * empty_str = "";
int i;
const int N = 1;
/* Parse the input tuple */
if(!PyArg_ParseTuple(args, "dd", &var1, &var2))
return NULL;
/* Binary structures */
struct libbinary_c_stardata_t *stardata[N];
struct libbinary_c_store_t *store = NULL;
/* Allocate memory for binaries */
for(i=0;i<N;i++){
stardata[i] = NULL;
David Hendriks
committed
binary_c_new_system(&stardata[i], NULL, NULL, &store, NULL, &empty_str, -1);
}
/* Return the evolved binary */
PyObject *ret = Py_BuildValue("");
return ret;
}
#endif //__DEPRECATED
static PyObject* binary_c_new_binary_system(PyObject *self, PyObject *args)
{
/* Binary structures */
struct libbinary_c_stardata_t *stardata;
/* Allocate memory for binaries */
char * empty_str = "";
stardata = NULL;
David Hendriks
committed
binary_c_new_system(&stardata, NULL, NULL, &store, NULL, &empty_str, -1);
/* Return an object containing the stardata */
PyObject *ret = Py_BuildValue("");
return ret;
}
static PyObject* binary_c_function_prototype(PyObject *self, PyObject *args)
{
// This function is an very bare example of how a function would look like.
double var1, var2;
/* Parse the input tuple */
if(!PyArg_ParseTuple(args, "dd", &var1, &var2))
{
return NULL;
}
else
{
/* Return the evolved binary */
PyObject *ret = Py_BuildValue("");
return ret;
}
}
David Hendriks
committed
Below are the real functions:
David Hendriks
committed
binary_c_run_population
David Hendriks
committed
binary_c_run_system
David Hendriks
committed
binary_c_return_arglines
binary_c_return_help_info
binary_c_return_help_all_info
binary_c_return_version_info
David Hendriks
committed
/* ============================================================================== */
/* Wrappers to functions that evolve binary systems. */
/* ============================================================================== */
David Hendriks
committed
static PyObject* binary_c_run_system(PyObject *self, PyObject *args, PyObject *kwargs)
{
David Hendriks
committed
static char* keywords[] = {"argstring", "custom_logging_func_memaddr", "store_memaddr", "persistent_data_memaddr", "write_logfile", "population", NULL};
David Hendriks
committed
/* set vars and default values for some*/
David Hendriks
committed
long int custom_logging_func_memaddr = -1;
long int store_memaddr = -1;
long int persistent_data_memaddr = -1;
David Hendriks
committed
int write_logfile = 0;
int population = 0;
// By using the keywords argument it scans over the given set of kwargs, but if they are not given then the default value is used
if(!PyArg_ParseTupleAndKeywords(args, kwargs, "s|lllii", keywords, &argstring, &custom_logging_func_memaddr, &store_memaddr, &persistent_data_memaddr, &write_logfile, &population))
David Hendriks
committed
// printf("Input persistent_Data_memaddr: %lu\n", persistent_data_memaddr);
David Hendriks
committed
/* Call c-function */
David Hendriks
committed
char * buffer;
char * error_buffer;
size_t nbytes;
David Hendriks
committed
int out MAYBE_UNUSED = run_system(argstring, // the argstring
custom_logging_func_memaddr, // memory adress for the function for custom logging
store_memaddr, // memory adress for the store object
persistent_data_memaddr, // memory adress for the persistent data
David Hendriks
committed
write_logfile, // boolean for whether to write the logfile
population, // boolean for whether this is part of a population.
David Hendriks
committed
&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);
David Hendriks
committed
/* Display error */
David Hendriks
committed
if(error_buffer != NULL && strlen(error_buffer)>0)
David Hendriks
committed
fprintf(stderr,
David Hendriks
committed
"Error in binary_c run (via binary_c_run_system): %s\n",
David Hendriks
committed
error_buffer);
}
Safe_free(buffer);
Safe_free(error_buffer);
David Hendriks
committed
return return_string;
}
David Hendriks
committed
/* ============================================================================== */
/* Wrappers to functions that call other API functionality like help and arglines */
/* ============================================================================== */
static PyObject* binary_c_return_arglines(PyObject *self, PyObject *args)
{
char * buffer;
char * error_buffer;
size_t nbytes;
int out MAYBE_UNUSED = return_arglines(&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);
return return_string;
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
}
static PyObject* binary_c_return_help_info(PyObject *self, PyObject *args)
{
/* Parse the input tuple */
char *argstring;
if(!PyArg_ParseTuple(args, "s", &argstring))
{
return NULL;
}
else
{
char * buffer;
char * error_buffer;
size_t nbytes;
int out MAYBE_UNUSED = return_help_info(argstring,
&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);
return return_string;
}
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
}
static PyObject* binary_c_return_help_all_info(PyObject *self, PyObject *args)
{
char * buffer;
char * error_buffer;
size_t nbytes;
int out MAYBE_UNUSED = return_help_all_info(&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);
return return_string;
David Hendriks
committed
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
}
static PyObject* binary_c_return_version_info(PyObject *self, PyObject *args)
{
char * buffer;
char * error_buffer;
size_t nbytes;
int out MAYBE_UNUSED = return_version_info(&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);
return return_string;
}
/* ============================================================================== */
/* Wrappers to functions that call other functionality */
/* ============================================================================== */
static PyObject* binary_c_return_store_memaddr(PyObject *self, PyObject *args)
David Hendriks
committed
{
char * buffer;
char * error_buffer;
size_t nbytes;
long int out MAYBE_UNUSED = return_store_memaddr(&buffer,
&error_buffer,
&nbytes);
/* copy the buffer to a python string */
PyObject * return_string MAYBE_UNUSED = Py_BuildValue("s", buffer);
PyObject * return_error_string MAYBE_UNUSED = Py_BuildValue("s", error_buffer);
PyObject * store_memaddr = Py_BuildValue("l", out);
// printf("store_memaddr: %ld\n", out);
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);
return store_memaddr;
}
static PyObject* binary_c_return_persistent_data_memaddr(PyObject *self, PyObject *args)
{
/* Python binding that wraps the c function which calls the binary_c api endpoint. */
char * buffer;
char * error_buffer;
size_t nbytes;
long int out MAYBE_UNUSED = return_persistent_data_memaddr(&buffer,
David Hendriks
committed
&error_buffer,
&nbytes);
/* copy the buffer to a python string */
David Hendriks
committed
PyObject * return_string MAYBE_UNUSED = Py_BuildValue("s", buffer);
David Hendriks
committed
PyObject * return_error_string MAYBE_UNUSED = Py_BuildValue("s", error_buffer);
PyObject * persistent_data_memaddr = Py_BuildValue("l", out);
// printf("persistent_data_memaddr: %ld\n", out);
David Hendriks
committed
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);
return persistent_data_memaddr;
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
}
/* Memory freeing functions */
// static PyObject* binary_c_free_store_memaddr(PyObject *self, PyObject *args)
// {
// /* Python binding that calls the c function that free's the store memory */
// /* Parse the input tuple */
// char *store_memaddr;
// if(!PyArg_ParseTuple(args, "l", &store_memaddr))
// {
// return NULL;
// }
// char * buffer;
// char * error_buffer;
// size_t nbytes;
// long int out MAYBE_UNUSED = free_store_memaddr(store_memaddr,
// &buffer,
// &error_buffer,
// &nbytes);
// /* copy the buffer to a python string */
// PyObject * return_string MAYBE_UNUSED = 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);
// return 0;
// }
static PyObject* binary_c_free_persistent_data_memaddr_and_return_json_output(PyObject *self, PyObject *args)
{
/* Python binding that calls the c function that free's the store memory */
/* Parse the input tuple */
long int persistent_data_memaddr = -1;
if(!PyArg_ParseTuple(args, "l", &persistent_data_memaddr))
{
return NULL;
}
char * buffer;
char * error_buffer;
size_t nbytes;
long int out MAYBE_UNUSED = free_persistent_data_memaddr_and_return_json_output(persistent_data_memaddr,
&buffer,
&error_buffer,
&nbytes);
/* copy the buffer to a python string */
PyObject * return_string MAYBE_UNUSED = 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);