8

我观察到,当一种类型

help

在 Python repl 中,一个得到

Type help() for interactive help, ...

当一种类型

help()

一个被踢到帮助模式。我很确定这是因为site._Helper定义了__repr__()(对于第一个示例)和__call__() (对于第二个示例)。

我喜欢这种行为(仅提示对象和可调用语法),并且我想对通过 SWIG 导出到 Python 的 C++ 类做同样的事情。这是我尝试做的一个简单示例

helpMimic.h
-----------
class HelpMimic
{
public:
    HelpMimic() {};
    ~HelpMimic() {};

    char *__repr__();
    void operator()(const char *func=NULL);
};

helpMimic.cxx
-------------
char *HelpMimic::__repr__()
{
    return "Online help facilities are not yet implemented.";
}

void HelpMimic::operator()(const char *func)
{
    log4cxx::LoggerPtr transcriptPtr = oap::getTranscript();
    std::string commentMsg("# Online help facilities are not yet implemented. Cannot look up ");
    if (func) {
        commentMsg += func;
    }
    else {
        commentMsg += "anything.";
    }

    LOG4CXX_INFO(transcriptPtr, commentMsg);
}

helpMimic.i
-----------
%module sample
 %{
#include <helpMimic.h>
 %}
class HelpMimic
{
public:
    HelpMimic() {};
    ~HelpMimic() {};

    char *__repr__();
    void operator()(const char *func=NULL);
};

当我尝试在我的应用程序中使用这个类时,我似乎无法在帮助下获得我看到的行为(下面的输出来自嵌入了 Python 的 C++ 应用程序,其中每个输入行都是通过发送的PyEval_String()):

 tam = sample.HelpMimic()
 tam   # echoes 'tam', nothing else
 print tam
 # _5010b70200000000_p_HelpMimic
 print repr(tam)
 # <Swig Object of type 'HelpMimic *' at 0x28230a0>
 print tam.__repr__()
 # Online help facilities are not yet implemented.

最后的打印显示该方法__repr__()存在,但我无法使用更简单的对象引用或使用repr(tam). 我还尝试定义__str()__希望我误解了哪个会被调用,但仍然没有运气。

我尝试使用%extend接口文件中的指令将一个__str__()或一个__repr__()定义插入到 SWIG 接口定义文件中,而不是直接在 C++ 中定义它们,但无济于事。

我错过了什么?

4

2 回答 2

3

正如@flexo 在评论中所建议的那样,如果您使用SWIG 代码生成器的-builtin标志repr(),则不会调用您的__repr__方法。相反,您需要定义一个适合 repr 槽的函数。

%feature("python:slot", "tp_repr", functype="reprfunc") HelpMimic::printRepr;

根据 HelpMimic::printRepr 必须具有与预期签名匹配的签名(Python 文档中的 tp_repr) - 它必须返回字符串或 unicode 对象。另一个警告 - 您不能将相同的功能放在多个插槽中,所以不要尝试将其用于 tp_str!

于 2015-06-02T19:45:54.733 回答
3

我通常使用 %extend 功能来避免为特定目标语言定制 C/C++。例如

%extend MyClass {
  %pythoncode %{
    def __repr__(self):
      # How you want your object to be shown
    __swig_getmethods__["someMember"] = SomeMemberGet
    __swig_setmethods__["someMember"] = SomeMemberSet
    if _newclass:
      someMember = property(SomeMemberGet,SomeMemberSet)
    def show(self):
      # You could possibly visualize your object using matplotlib
  %}
};

您在repr函数中的位置基本上可以调用任何函数并格式化输出以满足您的需要。此外,您可以添加属性并定义它们如何映射到 setter 和 getter。

于 2015-08-11T11:06:49.083 回答