Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python ctypes是ctypes.Structure的子类,不为指向结构的指针调用_Python_Python 3.x_Ctypes - Fatal编程技术网

Python ctypes是ctypes.Structure的子类,不为指向结构的指针调用

Python ctypes是ctypes.Structure的子类,不为指向结构的指针调用,python,python-3.x,ctypes,Python,Python 3.x,Ctypes,我包装的C库需要分配和销毁C函数内部结构的内存,并且总是传递指针,而不是结构 我有一个子类ctypes.Structure,使用\uu del\uu方法。在实例上调用del时不会调用此方法,该实例是指向从C中的函数返回的结构的指针(Foo_init)。有趣的是,当调用del时,如果该实例不是指针,而是从另一个C函数返回的实际值(Foo\u init\u value),就会调用它 如何获取\uuu del\uu方法来调用从C中的函数返回的结构指针 在Python中: import ctypes i

我包装的C库需要分配和销毁C函数内部结构的内存,并且总是传递指针,而不是结构

我有一个子类
ctypes.Structure
,使用
\uu del\uu
方法。在实例上调用
del
时不会调用此方法,该实例是指向从C中的函数返回的结构的指针(
Foo_init
)。有趣的是,当调用
del
时,如果该实例不是指针,而是从另一个C函数返回的实际值(
Foo\u init\u value
),就会调用它

如何获取
\uuu del\uu
方法来调用从C中的函数返回的结构指针

在Python中:

import ctypes
import gc
libfoo = ctypes.CDLL("libfoo.so")

class Foo(ctypes.Structure):
    _fields_ = [
        ('a', ctypes.c_int),
        ('b', ctypes.POINTER(ctypes.c_char)),
    ]
    def __del__(self):
        print('deleting')
        libfoo.Foo_destroy(self)

# Get a pointer to Foo
libfoo.Foo_init.restype = ctypes.POINTER(Foo)
libfoo.Foo_init.argtypes = None

# Get actual Foo, not pointer
libfoo.Foo_init_value.restype = Foo
libfoo.Foo_init_value.argtypes = None

libfoo.Foo_destroy.restype = ctypes.c_int
libfoo.Foo_destroy.argtypes = [ctypes.POINTER(Foo)]

# Get a pointer to Foo
foo = libfoo.Foo_init()
# Nothing is printed here:
del foo
# Nothing is printed here
gc.collect()
# Nothing is printed here
[f for f in gc.get_objects() if isinstance(f, Foo)]

# Get an actual Foo, not pointer
foo = libfoo.Foo_init_value()
# This works, prints 'deleting', but crashes with freeing an invalid pointer
# presumably because __del__ is passing the struct, not pointer to struct
del foo
以下是我的简单C库:

#include <stdlib.h>

typedef struct Foo {
    int a;
    char *b;
} Foo;

/* Allocate and return pointer to Foo */
/* __del__ does not work for this one */
Foo *Foo_init(void)
{
    Foo *foo = (Foo *) malloc(sizeof(Foo));
    foo->a = 0;
    foo->b = NULL;
    return foo;
}

/* Allocate and return value of Foo, not a pointer*/
/* __del__ works on this */
Foo Foo_init_value(void)
{
    Foo *foo = Foo_init();
    return *foo;
}

int *Foo_destroy(Foo *foo)
{
    if (foo->b) {
         free(foo->b);
         foo->b = NULL;
    }
    free(foo);
    return 0;
}

这是可行的,但我认为有更好的方法:

Foop = ctypes.POINTER(Foo)

def foo_del(self):
    print('deleting')
    libfoo.Foo_destroy(self)

Foop.__del__ = foo_del

foo = libfoo.Foo_init()
# prints 'deleting'
del foo

什么已经解决,什么可以改变?关于.dll,函数签名可以更改吗?@CristiFati函数签名不能更改;它们来自供应商提供的专有/传统API。
Foop = ctypes.POINTER(Foo)

def foo_del(self):
    print('deleting')
    libfoo.Foo_destroy(self)

Foop.__del__ = foo_del

foo = libfoo.Foo_init()
# prints 'deleting'
del foo