3

我正在为一个用 C++ 编写的小型音频库创建 Python 扩展。打开音频流时,回调函数作为参数传递(当然还有其他参数)。一个稍微简化的用例:

AudioThingy *a = new AudioThingy();
a->openStream(..., callbackFunction);
a->startStream();

我的 Python 扩展将它封装在一个 Python 类中。

thingy = AudioThingy()
thingy.openStream(..., pythonCallbackFunction)
thingy.startStream()

现在,扩展有一个作为 C 函数的回调,它传递给 C++ 库。对于每个流滴答,回调接收有关流的一些信息以及指向音频缓冲区的空指针,回调根据流格式参数将其转换为正确的数据类型。我的意图当然是让这个用 C 实现的回调函数以某种数组作为参数调用用户指定的 Python 函数,然后填充来自例如用 Python 打开的 wav 文件的音频数据。

这就是我想要做的,在代码中:

static int __audiothingy_callback(void *buffer, ...) {
  PyGILState_STATE state = PyGILState_Ensure();
  /*
      cast the void pointer to the correct data type (short, int, long, etc.)
      wrap it for Python somehow
  */
  PyEval_CallObject(the_python_function, arglist);
  PyGILState_Release(state);
  //proceed to fill the buffer with stuff passed back from python
  for (...)
    *casted_buffer++ = ????
  Py_DECREF(arglist);
  return 0;
}

TL;DR:如何在线程中将正确类型的可变数组从 C 传递给 Python 函数,然后该函数可用于填充音频缓冲区?也许它可以用不同于我上面描述的方式来完成?欢迎所有输入。

4

1 回答 1

2

我认为你可以做几件事。如果您使用的是 Python 2.7,您可以使用新的缓冲区协议创建一个 memoryview 对象:

然后,您需要从缓冲区创建一个 memoryview 对象:

另一种策略是导入数组模块,并使用它来创建所需类型的数组。你用:

然后,根据需要的类型构造数组:

PyObject *array = PyObject_CallFunction(array_type, "c", 'd');   

更简单的是,您可以只使用一个 bytearray 对象:

于 2013-02-23T01:05:03.020 回答