I modified and commented the example from https://docs.python.org/3.7/extending/embedding.html#pure-embedding to help you get started. The function itself still does the same thing at the very last line (out[0] = 2*in[0];
) because it'll be up to you to structure the data you're sending to the python function and then to unpack it to the output structure you want. What it does do is import a library called mymodule
then call mymodule.myfunction(10,42)
and recieves the result as a Long
Here's the official reference for the rest of the python c api. I'm not really a c/c++ developer, so this probably has some glaring errors, but the structure should be there for you to get started.
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <math.h>
__declspec(dllexport) void simuser(double t, double delt, double in, double* out) {
//copied and modified from https://docs.python.org/3.7/extending/embedding.html#pure-embedding
//typedefs
PyObject *pName, *pModule, *pFunc;
PyObject *pArgs, *pValue;
int i;
//spin up an interpreter
Py_Initialize();
//create a python string of the library you want to import
pName = PyUnicode_DecodeFSDefault("mymodule");
/* Error checking of pName left out */
//import our library
pModule = PyImport_Import(pName);
//garbage collect module string which is no longer needed
Py_DECREF(pName);
//if we successfully loaded the library
if (pModule != NULL) {
//get a function from that library by name
pFunc = PyObject_GetAttrString(pModule, "myfunction");
/* pFunc is a new reference */
//check if we got anything, and that it's callable (a function)
if (pFunc && PyCallable_Check(pFunc)) {
//create a tuple where we'll put (2) arguments to the python funciton we want to call
pArgs = PyTuple_New(2);
//cast a string to Long then to PyLong
pValue = PyLong_FromLong(atoi("10"));
//set it as the first element of the tuple
PyTuple_SetItem(pArgs, 0, pValue);
//cast another string as second argument
pValue = PyLong_FromLong(atoi("42"));
//set it as the second element of the tuple
PyTuple_SetItem(pArgs, 1, pValue);
//call your function with the tuple of arguments we created
pValue = PyObject_CallObject(pFunc, pArgs);
//garbage collect arguments
Py_DECREF(pArgs);
//if call returned without error
if (pValue != NULL) {
//convert output of funciton to regular Long from PyLong and print
printf("Result of call: %ld\n", PyLong_AsLong(pValue));
//garbage collect
Py_DECREF(pValue);
}
else {
//garbage collect
Py_DECREF(pFunc);
//garbage collect
Py_DECREF(pModule);
//print a useful error message hopefully and exit nonzero
PyErr_Print();
fprintf(stderr,"Call failed\n");
return 1;
}
}
else {
if (PyErr_Occurred())
PyErr_Print();
fprintf(stderr, "Cannot find function \"myfunction\"\n");
}
//garbage collect
Py_XDECREF(pFunc);
//garbage collect
Py_DECREF(pModule);
}
else {
PyErr_Print();
fprintf(stderr, "Failed to load \"%s\"\n", argv[1]);
return 1;
}
if (Py_FinalizeEx() < 0) {
return 120;
}
return 0;
out[0] = 2*in[0]; //actual function isn't changed because I don't know what your data looks like, but a python function is still called in the process
}