【问题标题】:SWIG typemap 2d array to Python listSWIG typemap 2d 数组到 Python 列表
【发布时间】:2022-01-06 14:09:18
【问题描述】:

这是question 的下一个级别。我需要将 2d C char 数组转换为 Python 列表。

Python 方面

device_info = getInfoFromCpp()
print(device_info.angles)
for angle in device_info.angles:
  print("Angel: " + angle)

错误

<Swig Object of type 'char (*)[MaxStringLength]' at 0x000000D8B2710330>
Execution error: 'SwigPyObject' object is not iterable

С++ 标头

struct DeviceInformation {
  static const int MaxStringLength= 200;
  static const int MaxNumberOfAngles= 5;

  char serialNumber[MaxStringLength];
  char angles[MaxNumberOfAngles][MaxStringLength];
};

基于@MarkTolonen 的answer,我尝试了以下typemaps,但没有结果。

// %typemap(out) char*[ANY] %{
// %typemap(out) char (*)[ANY] %{
%typemap(out) char [ANY][ANY] %{
    PyObject *pyArray = PyList_New(5);
    for (uint8_t i = 0; i < 5; ++i) {
        PyObject *pyString = PyString_FromString(reinterpret_cast<char*>($1[i]));
        PyList_SetItem(pyArray, i, pyString);
    }
    $result = pyArray;
%}

【问题讨论】:

  • “没有结果”是什么意思?我测试了你的类型图,它对我有用,尽管你应该使用$1_dim0 而不是硬编码的5 来获得更通用的类型图的列表长度。
  • 另外,PyString 是一个不推荐使用的名称。 SWIG 有一个兼容性#define,但正确的 API 是 PyUnicode_FromString。你也不需要投射,可以说PyUnicode_FromString($1[i])。请注意, PyUnicode_FromString 假定 char 数组以 UTF-8 编码,这可能不正确。 PyBytes_FromString() 只会给出没有编码假设的字节。
  • 是的,我也使用 $1_dim0,但是当我尝试 %typemap(out) char*[ANY]%typemap(out) char (*)[ANY] 时,我硬编码了数组大小。感谢您详细说明PyUnicode_FromStringPyString_FromStringPyBytes_FromString/ 之间的区别

标签: python c++ arrays char swig


【解决方案1】:

您的代码对我有用,但这里是问题 cmets 和一个工作示例中提到的一些更正:

test.i

%module test

// This works for any size of 2d char array assuming it contains
// UTF-8-encoded, null-terminated strings (no error checking!)
%typemap(out) char [ANY][ANY] %{
    $result = PyList_New($1_dim0);
    for (Py_ssize_t i = 0; i < $1_dim0; ++i) {
        PyList_SET_ITEM($result, i, PyUnicode_FromString($1[i]));
    }
%}

%inline %{
struct DeviceInformation {
  static const int MaxStringLength= 200;
  static const int MaxNumberOfAngles= 5;

  char serialNumber[MaxStringLength];
  char angles[MaxNumberOfAngles][MaxStringLength];
};

// test function
DeviceInformation getInfoFromCpp() {
    return {"serialnumber",{"angle1","angle2","angle3","angle4","angle5"}};
}
%}

演示:

>>> import test
>>> x=test.getInfoFromCpp()
>>> x.serialNumber
'serialnumber'
>>> x.angles
['angle1', 'angle2', 'angle3', 'angle4', 'angle5']

【讨论】:

  • 是的,当我在 %module ... 指令之后将 typemap 规则放在 SWIG 文件的大多数顶部时,我的代码终于可以工作了。但如果没有你的帮助,我不确定我能这么快成功。
  • @den 是的,您必须在 SWIG 处理创建包装器代码的行之前定义规则:) 最好在我的答案中发布minimal reproducible example 以重现该问题。将来将问题减少到一个小的test.i 并将其发布在问题中。使用修复程序对其进行编辑然后从头开始编写它会更容易,并且它清楚地表明(如在本例中)代码可能定位不正确。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-03
  • 1970-01-01
  • 2011-08-12
  • 1970-01-01
相关资源
最近更新 更多