Reputation: 71
I am having a really hard time figuring out how to pass a large byte array of data from C to an arbitrary Python3 function. For reference, here are some documentation links on the subject:
https://docs.python.org/3.5/extending/embedding.html
Most of the information in the docs seems to assume that I am passing data from Python to C. I need to do the opposite. I found the a reference to the API function PyBuffer_FromContiguous
– but it is not documented anywhere (that I can find). The function prototype is here:
PyAPI_FUNC(int) PyBuffer_FromContiguous(Py_buffer *view, void *buf,
Py_ssize_t len, char order);
Basically I have two questions:
Py_buffer
object? Is this even the right approach?Py_buffer
is constructed, how do I associate the Py_buffer
with a PyObject
that can be set to a input tuple/argument for a call to a python function?Here is a code sample for what I am attempting (updated to include the data_s
typedef):
typedef struct
{
size_t size;
unsigned char* data;
} data_s;
// convert the arguments
PyObject* pArgs;
PyObject* pRes;
Py_buffer* pBuf;
pArgs = PyTuple_New((Py_ssize_t)num_args);
if (num_args)
{
va_start(argp, num_args);
for (i = 0; i < num_args; i++)
{
data_s* arg = va_arg(argp, data_s*);
result = PyBuffer_FromContiguous(pBuf, arg->data, (Py_ssize_t)arg->size, 'C');
if (result < 0)
{
fprintf(stderr, "Error: Unable to copy argument %d into python object\n", i);
PY_DECREF(pArgs);
break;
}
// set pValue, something like this?
PyTuple_SetItem(pArgs, i, pBuf->obj);
}
}
// run the function
pRes = PyObject_CallObject(func_entry->pFunc, pArgs);
// error checking...
… I would really appreciate any leads on these issues.
Upvotes: 3
Views: 1568
Reputation: 71
The problem was that I was not finding the right API call for what I needed. Here is the call (in case anyone cares) that solves this problem: Py_BuildValue
and is documented here:
https://docs.python.org/3/extending/extending.html#building-arbitrary-values
Upvotes: 1