【问题标题】:Calling SWIG generated code from Python interpreter从 Python 解释器调用 SWIG 生成的代码
【发布时间】:2013-07-25 22:37:16
【问题描述】:

我正在尝试使用 SWIG 从 Python 调用 C++ 对象的成员函数。目前我有一个带有 getter 和 setter 的小示例类来修改 C++ 类的成员变量。这是C++头文件:

#ifndef _square_
#define _square_
#include <iostream>

class Square
{
 private:
    double x;
    double y;
    const char *name;

 public:
    void setName(const char*);
    const char* getName();
    Square() {
        name = "construct value";
    };
};
#endif

这里是.cpp实现文件:

#include <iostream>
using namespace std;
#include "Square.h"

const char* Square::getName()
{
    return name;
}

void Square::setName(const char* name)
{
    this->name = name;
    return;
}

还有 SWIG 的 Square.i 文件:

%module Square
%{
#include "Square.h"
%}

%include "Square.h"

SWIG 似乎可以毫无问题地生成 Square_wrap.cxx 文件,并且生成的目标文件似乎可以正常链接:

$ swig -python -c++ Square.i
$ g++ -c -fpic Square.cxx Square_wrap.cxx -I/usr/include/python2.7
$ g++ -shared Square.o Square_wrap.o -o _Square.so

现在用一些 Python 示例来测试结果:

$ cat test2.py
#!/usr/bin/python
import Square

s = Square.Square()

print s.getName()
s.setName("newnametest")
print s.getName()

如果我通过 Python 解释器运行它,一切正常:

$ python test2.py
construct value
newnametest

但是如果我通过 Python 的 CLI 交互地输入测试行,事情就不起作用了:

$ python
Python 2.7.4 (default, Apr 19 2013, 18:28:01) 
[GCC 4.7.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import Square
>>> 
>>> s = Square.Square()
>>> 
>>> print s.getName()
construct value
>>> s.setName("newnametest")
>>> print s.getName()

>>> s.getName()
'<stdin>'
>>> s.setName('newnametest')
>>> s.getName()
''
>>> s.setName("newnametest")
>>> s.getName()
''

与 CLI 相比,Python 在后台处理 Python 脚本文件的方式是否不同,还是我以某种方式滥用了 SWIG 生成的 Python 接口?任何有关如何调试或理解底层问题的提示将不胜感激。

【问题讨论】:

    标签: c++ python swig interpreter


    【解决方案1】:

    据我所知,您只是将引用存储在 cpp 文件 (this-&gt;name = name) 上。复制它会很好,因为字符串很可能不够持久,并且在函数返回后被丢弃(并且在那之后稍微收集垃圾)。这可以解释为什么它在脚本中起作用(两次调用之间没有 GCollection 也没有发生任何其他事情)。

    尝试使用strdupstd::string 进行复制。

    【讨论】:

    • 这绝对可以解释差异,除了我尝试使用import gcgc.disable() 禁用垃圾收集器但仍然收到相同的结果。除非有其他方法,否则这似乎有助于保持 CLI 命令之间的状态。
    • 虽然你是对的:复制字符串确实可以解决问题。感谢您提供一些见解! void Square::setName(const char* name) { this-&gt;name = strdup(name); return; }
    • @xsquared 是的,它可以是很多东西,不知道ctypes的内部是否足够好,但你需要记住,当调用返回时该值将被丢弃。
    猜你喜欢
    • 2014-07-25
    • 1970-01-01
    • 2012-12-18
    • 2012-05-04
    • 2017-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多