python - swig 将元组列表传递给 C++ 函数

标签 python c++ swig

我正在尝试学习 SWIG,尝试将它与 python 中的其他 C++ 包装器进行比较。我想写的功能之一是这样的:

obj = MyObj()
obj.add([(1,2,), (3,4.0,), (5,"six","string",)])

add 需要获取一个元组列表,这些元组的大小要么是 2 要么是 3,并且不是所有统一类型(因为,你知道,Python)。在 SWIG 中执行此操作的最简单方法是什么(最终我希望此代码调用 obj.add_int(1, 2)obj.add_double(3, 4.0),在实际的 C++ 对象上)。

最佳答案

如果是我在 SWIG 中这样做,我会尽量编写尽可能少的奇怪的额外代码。因此,我最初的方法是编写一些 Python 代码来处理异构列表,并确定为列表中的每个条目调用哪个 add_TYPE

举个例子:

%module test

%{
#include <iostream>
#include <limits>
%}

%include <std_string.i>

%inline %{
  struct MyObj {
    void add_double(unsigned a, const double& b, const double& c=std::numeric_limits<double>::quiet_NaN()) {
      std::cout << "add_double(): " << a << ", " << b << ", " << c << "\n";
    }

    void add_int(unsigned a, int b, int c=~0) {
      std::cout << "add_int(): " << a << ", " << b << ", " << c << "\n";
    }

    void add_string(unsigned a, const std::string& b, const std::string& c="") {
      std::cout << "add_string(): " << a << ", " << b << ", " << c << "\n";
    }
  };
%}

%pythoncode %{
def obj_add(self, items):
  tries = (self.add_int, self.add_double, self.add_string)

  for args in items:
    for method in tries:
      good = False
      try:
        method(*args)
      except NotImplementedError:
        pass # Just pick a different version
      else:
        good = True
        break

    if not good: raise TypeError('No matches')

MyObj.add = obj_add
%}

为了方便演示,我在一个 %inline 指令中声明、定义和包装了所有 MyObj。您可能对此略有不同,例如重载而不是默认参数来区分两个/三个 arg 版本可能很有意义,并且也可以与 SWIG 一起“正常工作”。

add 的魔力完全是用 Python 使用老式的 ducktyping 编写的。作为纯 Python,您可能想要采用的所有常用方法都是开放的 - 遍历列表并使用 try 来处理失败,直到我选择一个工作。 (值得注意的是,你尝试它们的顺序很重要——如果 double 出现在 int 之前,那么你永远不会选择 int 而不是 double)。

这足以让我运行:

from test import *

obj = MyObj()
obj.add([(1,2,), (3,4.0,), (5,"six","string",)])

print('Done')

一旦我编译了它:

swig -py3 -c++ -python -Wall test.i
g++ -Wall -Wextra test_wrap.cxx -I/usr/include/python3.4/ -lpython3.4m -shared -o _test.so

结果如预期:

add_int(): 1, 2, -1
add_double(): 3, 4, nan
add_string(): 5, six, string
Done

您可以通过多种其他方式解决此问题,最明显的其他选择是使用大量 Python C API 调用(PyFloat_CheckPyInt_Check 等),但是当我们只能依赖现有的 SWIG 行为时,编写更难的代码来维护代码似乎需要付出很多努力。

关于python - swig 将元组列表传递给 C++ 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26999073/

相关文章:

java - 将 SWIG 与 C++ 的 std::map 一起使用时,Java 没有迭代器

python - 更新切片列表

python - 出于某种原因,我无法导入 office365.sharepoint.file

python - Bash 或 Python,当向终端打印字符时,如何在 FIXED 位置更改字符?

python - Django "extra"查询

c++ - 尝试解决段错误

c++ - 如何在同一行格式化右对齐和左对齐?

java - 将 C++ 回调转换为 Java

c++ - 使用 SFML 绘制函数

c++ - Lua + SWIG 猴子补丁