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 python 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_docstring[] =
"Return the store memory adress that will be passed to run_population";
David Hendriks
committed
// static struct libbinary_c_store_t *store = NULL;
David Hendriks
committed
/* Initialize pyobjects */
//
#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(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", binary_c_return_store, METH_VARARGS, return_store_docstring},
{NULL, NULL, 0, NULL}
};
David Hendriks
committed
/* ============================================================================== */
/* Making the module */
/* ============================================================================== */
/* */
// TODO: enforce python3
#if PY_MAJOR_VERSION >= 3
/* 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);
}
#else
/*
* Python pre-V3
*
* NOT TESTED THOROUGHLY!
*/
PyMODINIT_FUNC initbinary_c(void)
{
David Hendriks
committed
PyObject *m = Py_InitModule3("binary_c_python_api", module_methods, module_docstring);
if(m == NULL)
return;
}
#endif // Python version check
David Hendriks
committed
/* ============================================================================== */
/* Some wierd function */
/* ============================================================================== */
#ifdef __DEPRECATED
static PyObject* binary_c_create_binary(PyObject *self, PyObject *args)
{
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
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;
binary_c_new_system(&stardata[i], NULL, NULL, &store, &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;
binary_c_new_system(&stardata, NULL, NULL, &store, &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
David Hendriks
committed
static char* keywords[] = {"argstring", "custom_logging_func_memaddr", "store_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;
int write_logfile = 0;
int population = 0;
David Hendriks
committed
if(!PyArg_ParseTupleAndKeywords(args, kwargs, "s|llii", keywords, &argstring, &custom_logging_func_memaddr, &store_memaddr, &write_logfile, &population))
David Hendriks
committed
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
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
/*
* TODO
* return the return_error_string as well!
*/
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);
/*
* TODO
* return the return_error_string as well!
*/
return return_string;
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
}
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;
}
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
}
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
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
}
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(PyObject *self, PyObject *args)
{
/* Parse the input tuple */
char *argstring;
if(!PyArg_ParseTuple(args, "s", &argstring))
{
return NULL;
}
char * buffer;
char * error_buffer;
size_t nbytes;
long int out MAYBE_UNUSED = return_store(argstring,
&buffer,
&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 * return_store_memaddr = Py_BuildValue("l", 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);
/*
* TODO
* return the return_error_string as well!
*/
return return_store_memaddr;