代码之家  ›  专栏  ›  技术社区  ›  tauran

Python引用计数和ctypes

  •  5
  • tauran  · 技术社区  · 15 年前

    你好,

    我在理解python引用计数时遇到了一些困难。 我要做的是使用ctypes模块将一个元组从c++返回到python。

    C++:

    PyObject* foo(...)
    {
    
      ...
      return Py_BuildValue("(s, s)", value1, value2);
    }
    

    pointer = c_foo(...) # c_foo loaded with ctypes
    obj = cast(pointer, py_object).value
    

    我不确定obj的裁判人数,所以我试着 sys.getrefcount() 得到了 3 2 (在 getrefcount 函数生成一个ref本身)。

    现在我做不到 Py_DECREF() 在C++返回之前,因为对象被删除。我可以减少python中的ref计数吗?

    编辑 调用cast函数时ref count会发生什么情况?我不太确定从下面的文件。 http://docs.python.org/library/ctypes.html#ctypes.cast

    ctypes.cast(obj,类型) 此函数类似于C中的cast运算符。它返回一个指向与obj相同的内存块的新类型实例。类型必须是指针类型,而obj必须是可以解释为指针的对象。

    2 回复  |  直到 15 年前
        1
  •  5
  •   tauran    15 年前

    在进一步的研究中,我发现可以指定函数的返回类型。 http://docs.python.org/library/ctypes.html#callback-functions 这使得转换过时,ref计数不再是一个问题。

    clib = ctypes.cdll.LoadLibrary('some.so')
    c_foo = clib.c_foo
    c_foo.restype = ctypes.py_object
    

    由于没有给出额外的答案,我接受我的新解决方案作为答案。

        2
  •  4
  •   ThR37    15 年前

    official C-API 这有点奇怪,因为ctypes通常用于在python中使用经典的c类型(比如int、float等等)。

    我个人“单独”使用C-API(不使用ctypes),但根据我个人的经验,在这种情况下,您不必担心引用计数器,因为您返回的是带有 Py_BuildValue . 当函数返回对象时 所有权 将返回的对象的指定给调用函数。

    Py_XINCREF / Py_XDECREF (比 Py_INCREF Py_DECREF 因为它接受空指针)仅当您要更改对象的所有权时:

    F = py_Map["key"]
    

    但由于所有权是给调用函数的,所以在删除时将调用析构函数 F

    解决方案是用c++在[]的包装器中编写:

    ...
    PyObject* result; // My py_Foo object
    Py_XINCREF(result); // transfer the ownership
    return result;
    }
    

    你应该看看 borrowed and owned reference

    推荐文章