C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了SWIG,C和Python:C临时对象过早删除大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个SWIG过早删除临时C对象的问题.

Python测试脚本的示例输出

--------------------------------------------------------------------------------
Works as expected:
    b0 =  Buffer(0,)
    b1 =  Buffer(1,1,)
    b0 =  Buffer(0,)
    y  =  Buffer(0,)
    repr(b0) =  Buffer(id = 0,vector at 0x020bf450,data at 0x020aeb30,size = 6)
    repr(y)  =  Buffer(id = 0,size = 6)
Funny business:
    deleting Buffer(id = 2)
    deleting Buffer(id = 3)
    repr(b2) =  Buffer(id = 2,vector at 0x020bf790,data at 0x00,size = 4257068)
    deleting Buffer(id = 4)
    repr(b3) =  Buffer(id = 4,vector at 0x02037040,data at 0x0204a4e0,size = 6)
    deleting Buffer(id = 0)
    deleting Buffer(id = 1)

删除缓冲区(id = X)是从Buffer :: ~Buffer()C代码生成的,所以我们在这里可以看到,在Funny业务部分,C Buffer对象被过早删除了! Python对象b2和b3应该保持对id = 2和id = 4的C Buffer对象的引用.

我的所有代码都附在我的博客post上.但是,我将在这里总结一下代码

Buffer.hpp:

#include <vector>
#include <String>

struct Buffer
{
    Buffer();
    Buffer(const Buffer & copy);
    ~Buffer();

    Buffer & operator=(const Buffer & rhs);

    Buffer & operator<<(const Buffer & rhs);
    Buffer & operator<<(double rhs);

    std::string __str__() const;
    std::string __repr__() const;

    private:

    std::vector<double> _data;
    int                 _id;
};

swig_test.i:

%module swig_test

%include "std_String.i"

%{
    #include "Buffer.hpp"
    #include <iostream>
%}

%ignore Buffer::operator=;

%include "Buffer.hpp"

go_test.py:

from swig_test import Buffer


def zeros(n):
    '''
    Returns a Buffer filled with 'n' zeros.
    '''

    b = Buffer()

    for i in xrange(n):
        b << 0.0

    return b


def ones(n):
    '''
    Returns a Buffer filled with 'n' ones.
    '''

    b = Buffer()

    for i in xrange(n):
        b << 1.0

    return b


def main():

    #--------------------------------------------------------------------------
    # This sections works as expected

    print "-" * 80
    print "Works as expected:"

    b0 = zeros(3)

    print "    b0 = ",b0

    b1 = ones(3)

    print "    b1 = ",b1

    y = b0 << b1

    print "    b0 = ",b0
    print "    y  = ",y
    print "    b1 = ",b1

    print "    repr(b0) = ",repr(b0)
    print "    repr(y)  = ",repr(y)

    #--------------------------------------------------------------------------
    # Funny things are happening here!

    print "Funny business:"

    b2 = zeros(3) << ones(3)

    print "    repr(b2) = ",repr(b2)

    b3 = zeros(3) << 4.0

    print "    repr(b3) = ",repr(b3)


if __name__ == "__main__":
    main()

我在博客文章中已经尝试了一些SWIG的东西,但我的SWIG-foo技能已经缩短了.

救救我社区,你是我唯一的希望!

更新1

我怀疑我有多个PyObjects将Buffer *保存到同一个C Buffer对象,所以当临时PyObject被垃圾收集时,它会删除C Buffer *.

所以,我想我需要一个Py_INCREF,但在哪里呢?

更新2

尝试按照jarod42的建议按值返回会破坏串联范例,例如:

b = Buffer()
b << 1 << 2 << 3
print b

只生产:

Buffer(1,)

所以这不是我想要的.

%newobject指令可用于释放函数方法创建的新创建的对象(防止内存泄漏).在这种情况下,Buffer :: operator<<没有创建新对象.

解决方法

经过一番搜索后,我遇到了这个 thread,最终导致了一个有效的解决方案.

将typemap(out)与Py_INCREF结合使用就可以了.

swig_test.i:

%module swig_test

%include "std_String.i"

%{
    #include "Buffer.hpp"
    #include <iostream>
%}

%ignore Buffer::operator=;

%typemap(out) Buffer & operator<<
{
    if(result) { /* suppress unused warning */ }
    Py_INCREF($self);
    $result = $self;
}

%include "Buffer.hpp"

现在我得到了我想要的行为(它与纯Python实现相匹配)并且没有内存泄漏.

大佬总结

以上是大佬教程为你收集整理的SWIG,C和Python:C临时对象过早删除全部内容,希望文章能够帮你解决SWIG,C和Python:C临时对象过早删除所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。