3

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:

  1. Is this the right way to construct a Py_buffer object? Is this even the right approach?
  2. Once the 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.

fish2000
  • 4,289
  • 2
  • 37
  • 76
sean
  • 61
  • 7
  • 1
    You're creating a buffer, but not using it. What are you trying to do? Usually, you'd want to use something like [`PyBuffer_FillInfo`](https://docs.python.org/3/c-api/buffer.html#c.PyBuffer_FillInfo), but it's not clear what the goal here is. Buffers must be associated with a Python object, is `data_s` as `PyObject` of some sort? – ShadowRanger Nov 17 '15 at 02:39
  • @ShadowRanger: You might be right. I was attempting to use the Py_buffer in the `PyTuple_SetItem()` call. I am trying to call an arbitrary function with arbitrary data. Maybe it isn't valid to set the buffer PyObject to a tuple like that? I did see some documentation on the `PyBuffer_FillInfo` function, but I was assuming that the `PyObject* exporter` needed to exist before I could use it to set the value of the Py_buffer. It seemed the opposite direction for what I need. – sean Nov 17 '15 at 04:08

1 Answers1

1

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

sean
  • 61
  • 7