用Python封装的C++类的SIP补丁
我正在为一个用C++写的库创建一个Python的封装,这个库实现了一些底层的机器对机器(M2M)通信。我使用的是Riverbank的SIP封装生成器。
这个C++类里面有一个方法:
class Bar {
public:
enum Status {
...
};
void setStatus(Status s);
Status getStatus() const;
...
};
这个类在模块foo
里面。
SIP使用了它自己的一种枚举类型,但出于一些原因,我想用Python 3.4标准库里的枚举。
我觉得通过Python的C API访问Python定义的类几乎不可能,所以我决定在__init__.py
里对封装的类进行修改。这样做的主要原因是我想在C/C++/SIP中处理一些底层的工作,然后在Python中对这个类进行优化(比如添加参数验证,并给出合理的错误信息)。
Python的__init__.py
部分大概是这样的:
from foo import Bar
class Status(IntEnum):
ONE = 1
TWO = 2
... and so on ...
Status.__module__ = 'Bar.Status'
Bar.Status = Status
Bar.status = property(...)
Bar.status
将会接受并返回一个好用的、符合Python风格的Bar.Status
枚举。
我期望的结果是这样的:
class Bar(object):
class Status(IntEnum):
...
...
我在想,这种方法是否有什么问题,特别是在导入时对对象进行修改。
1 个回答
1
我用另一种方法解决了这个问题,感觉还不错。
我们来看看一个C++库,它里面有两个类:
- Foo
- FooFactory
这个包装库包含了一个叫做 libfoo
的包(是用Python的C API创建的),还有一个更符合Python风格的包 foo
(是用普通的Python创建的)。我们并不直接使用 libfoo
包,而是导入 foo
。
包 foo
的 __init__.py
文件内容如下:
from libfoo import Foo, FooFactory
# both are naked wrappers with ugly API derived from C++
# I defined some pythonic sugar that makes them nice to use
class FooPythonicGoodies(object):
# add pythonic goodies here
def quack(self):
pass
# Merge them
Foo.__bases__ = Foo.__bases__ + (FooPythonicGoodies,)
现在,当我在代码的任何地方这样做的时候:
from foo import Foo, FooFactory
a = Foo()
a.quack()
# Factory is a C++ wrapped class that returns wrapped foo
# objects WITH FooPythonicGoodies!
factory = FooFactory()
b = factory.create_foo()
b.quack() # that works too!
这样我就可以用更符合Python风格的API来美化那些不太符合Python风格的C++类。