为扩展模块中用户定义的 python 类提升 Python to_python_converter

Posted

技术标签:

【中文标题】为扩展模块中用户定义的 python 类提升 Python to_python_converter【英文标题】:Boost Python to_python_converter for user defined python class in extension module 【发布时间】:2013-12-29 07:32:10 【问题描述】:

我想从我的 C++ 扩展模块返回以下 python 类的实例,它模仿 boost::tribool 的三态逻辑:

class Tribool(object):

def __init__(self, value = None):
    if any(value is v for v in (False, True, None)):
        self.value = value
    else:
        raise ValueError("Tribool must be False, True or None")

def __nonzero__(self):
    raise TypeError("Tribool may not be used as an implicit bool")

def __eq__(self, other):
    if isinstance(other, Tribool):
        return self.value is other.value
    if any(other is v for v in (False, True, None)):
        return self.value is other
    raise TypeError("Tribool can only be compared to another Tribool or False, True, or None")

def __ne__(self, other):
    return not (self == other)

def __invert__(self):
    if self.value is False:
        return Tribool(True)
    elif self.value is True:
        return Tribool(False)
    elif self.value is None:
        return Tribool(None)
    raise ValueError("Tribool must be False, True or None")

def __and__(self, other):
    if (self.value is False) or (other.value is False):
        return Tribool(False)
    if (self.value is None) or (other.value is None):
        return Tribool(None)
    return Tribool(True)

def __or__(self, other):
    if (self.value is True) or (other.value is True):
        return Tribool(True)
    if (self.value is None) or (other.value is None):
        return Tribool(None)
    return Tribool(False)

def __xor__(self, other):
    if (self.value is None) or (other.value is None):
        return Tribool(None)
    if self == other:
        return Tribool(False)
    return Tribool(True)

def __str__(self):
    if any(self.value is v for v in (False, True, None)):
        return str(self.value)
    raise ValueError("Tribool must be False_, True_ or Maybe_")

def __repr__(self):
    return "Tribool(%s)" % str(self)

我相信我需要编写一个 to_python_converter,但我不知道如何为用户定义的 python 类型编写一个转换器。我已经阅读了 Boost Python 文档并使用 Google 进行了搜索,但没有找到一个可以借鉴的好例子。任何帮助表示赞赏。


更新

以下 C++ 代码会将 tribool 转换为 Python 值 True、False 和 None,这是部分解决方案:

struct tribool_to_Tribool

    static PyObject *convert(tribool const& value)
    
        if (value == true) return boost::python::incref(boost::python::object(true).ptr());
        else if (value == false) return boost::python::incref(boost::python::object(false).ptr());
        else return boost::python::incref(boost::python::object().ptr());
    
;

to_python_converter<tribool,tribool_to_Tribool>();

我无法弄清楚的部分是如何返回纯 Python Tribool 类的实例,而不是从转换例程返回值 True、False 和 None。

【问题讨论】:

对于三态逻辑,Python Tribool module 可能对你有用。 【参考方案1】:

这可以通过从 Python 方法返回 Tribool 的相同方式完成。在任何一种语言中,都需要获取Tribool Python 类对象的句柄,然后调用它。返回的对象将是Tribool 类型的实例。

例如:

from tribool import Tribool
x = Tribool(False)

相当于:

namespace python = boost::python;
python::object tribool_class = python::import("tribool").attr("Tribool");
python::object x = tribool_class(false);

下面是一个简化示例,其中用户定义的 Python 模块 (spam) 包含一个 Python 类 (Spam),而 C++ Python 扩展模块 (example) 提供了一个 make_spam 函数来创建 @987654330 @对象。

spam.py Python 模块:

class Spam(object):

    def __init__(self, value):
        self.value = value

    def __str__(self):
        return self.__repr__() + " has a value of " + str(self.value)

example.cpp 扩展模块:

#include <boost/python.hpp>

boost::python::object make_spam(boost::python::object value)

  // from spam import Spam
  // return Spam(value)
  return boost::python::import("spam").attr("Spam")(value);


BOOST_PYTHON_MODULE(example)

  boost::python::def("make_spam", &make_spam);

交互式 Python:

>>> import example
>>> print example.make_spam(False)
<spam.Spam object at 0xb74be1ac> has a value of False
>>> print example.make_spam(True)
<spam.Spam object at 0xb74be10c> has a value of True
>>> print example.make_spam(None)
<spam.Spam object at 0xb74be1ac> has a value of None

【讨论】:

第二个代码 sn-p 是我遗漏的一条信息——如何在 C++ 端获取纯 Python 类的句柄。现在一切正常。我假设python::import("tribool ") 表达式中的额外空间是多余的? @RandomBits 很高兴它为您工作。另外,是的,额外的空间——我已经把它编辑掉了。

以上是关于为扩展模块中用户定义的 python 类提升 Python to_python_converter的主要内容,如果未能解决你的问题,请参考以下文章

python模块是类吗

如何导入Python模块

Python模块序列化模块

Cython 将扩展模块传递给 python 导致 to_py_call_code 错误

python中如何调用自己写的函数

python基础九(模块和包)