【问题标题】:Python extension in C - passing lists back and forthC 中的 Python 扩展 - 来回传递列表
【发布时间】:2017-12-27 22:39:06
【问题描述】:

我有一个用于设备的 C 库,其中包含以下功能:

int GetDevInfo(int *devices);

在这种情况下,devices 是一个整数数组,可能会这样定义:

int devices[10]

该函数将通过硬件总线循环查找活动设备。当它找到它们时,它会将设备号放入devices[] 中的下一个可用位置,例如在扫描之前:

devices = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 和一个全局变量 DeviceCount 知道有 0 个活动变量。该函数发挥其魔力并决定设备 5 和 8 处于活动状态。那么:

devices = {5, 8, 0, 0, 0, 0, 0, 0, 0, 0}DeviceCount 知道有 2 个。

我希望 Python 函数是这样的。

devices = list(range(64))
for i in range(0,len(devices)):  # Set them all to 0
    devices[i] = 0
DeviceCount = 0

# Now we'll update it
DeviceCount = myModule.GetDevInfo(DeviceCount, devices)

返回时,DeviceCount 可能设置为 2,设备如下所示:

[5, 8, 0, 0, 0, 0, 0, 0, 0, 0]

我已经为其他传入整数和传回字符串的包装器编写了代码,但我没有找到任何网络智慧来帮助我解决这个问题。我知道我是否会这样做:

def f(a, data):
    a.append(data)

l = [1, 2, 3]
f(l, 4)

我得到了l=[1, 2, 3, 4],但如何使用 Python 包装器到 C 来获得这种效果并不明显。

【问题讨论】:

  • 建议:让函数只返回一个列表,其中len(that_list) == DeviceCount

标签: c python-3.x parameters wrapper


【解决方案1】:

好的,稍后阅读网络并进行大量试验和错误...

static PyObject* LMS_module_timesTwo(PyObject *self, PyObject *args)
{
  int i, numLines;
  PyObject *listObj, *numObj;
  unsigned int n;

  n = PyTuple_Size(args);
  if (1 == n) {
    /* argument 1 should be an list of integers */
    listObj = PyTuple_GetItem(args, 0);
    /* get the number of elements in the list */
    numLines = PyList_Size(listObj);

    /* should raise an error here. */
    if (numLines < 0)   return NULL; /* Not a list */

    for (i=0; i<numLines; i++) {
      numObj = PyList_GetItem(listObj, i);
      n = PyLong_AsUnsignedLong(PyNumber_Long(numObj));
      // This is the action - multiply by 2 for the test case
      n = n * 2;
      PyList_SetItem(listObj, i, Py_BuildValue("i", n));
    }
  } else {
      PyErr_SetString(PyExc_ValueError, "Function expects one argument");
      return NULL;
  }
  return PyLong_FromLong(1);
}

将该代码作为扩展的一部分(我省略了其他结构位,但如果有人需要,可以发布整个内容),作为 Python 3 测试程序,它运行得非常好!

   import my_module

   testlist = [1, 2, 3, 4, 5]
   print("List before multiplying = ",testlist)
   my_module.timesTwo(testlist)
   print("List after multiplying = ",testlist)

感谢所有阅读本文并思考答案的人。我的实际代码也有错误检查和内容,我不关心如果程序通过垃圾会发生什么,因为这是一个非常具体的功能。

问题最初提出的是将列表作为数组传递给 C 函数,所以这更接近最终结果:

static PyObject* LMS_module_timesTwo(PyObject *self, PyObject *args)
{
  int i, numLines;
  PyObject *listObj, *numObj;
  unsigned int n;
  unsigned int carray[64];  // this has to be big enough!

  n = PyTuple_Size(args);
  if (1 == n) {
    /* argument 1 should be an list of integers */
    listObj = PyTuple_GetItem(args, 0);
    /* get the number of elements in the list */
    numLines = PyList_Size(listObj);

    /* should raise an error here. */
    if (numLines < 0)   return NULL; /* Not a list */

    for (i=0; i<numLines; i++) {
      numObj = PyList_GetItem(listObj, i);
      carray[i] = PyLong_AsUnsignedLong(PyNumber_Long(numObj));
    }
    /* Do the actual work on the array */
    someCfunction(carry);  // this modifies the array somehow
    for (i=0; i<numLines; i++) {
      PyList_SetItem(listObj, i, Py_BuildValue("i", carray[i]));
    }
  } else {
      PyErr_SetString(PyExc_ValueError, "Function expects one argument");
      return NULL;
  }
  return PyLong_FromLong(1);
}

【讨论】:

    猜你喜欢
    • 2012-05-25
    • 2014-04-22
    • 1970-01-01
    • 2016-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-06
    • 2017-02-24
    相关资源
    最近更新 更多