AttributeError: бесплатно при переходе в собственность или освобождении cdata - PullRequest
1 голос
/ 16 марта 2019

Если я хочу стать владельцем указателя, который был malloc издан в C, документы для пакета Python cffi и этот ответ скажем, использовать ffi.gc с lib.free в качестве деструктора. Однако, когда я делаю это, я получаю AttributeError: free на вызов lib.free. Где определено lib.free? 1012 *

from tempfile import TemporaryDirectory
from weakref import WeakKeyDictionary

from cffi import FFI

common_header = """
typedef struct {
  int32_t length;
  double* values;
} my_struct;
"""

# FFI
ffi = FFI()

ffi.cdef(common_header + """
int func(my_struct*);
""")
ffi.set_source('_temp', common_header + """
int func(my_struct *input) {
  double* values = malloc(sizeof(double) * 3);
  input->length = 3;
  input->values = values;
  return 0;
}
""")

with TemporaryDirectory() as temp_dir:
    lib_path = ffi.compile(tmpdir=temp_dir)

    lib = ffi.dlopen(lib_path)

    func = lib.func

# Using the library
my_struct = ffi.new('my_struct*')
func(my_struct)

# Taking ownership of the malloced member
global_weakkey = WeakKeyDictionary()
global_weakkey[my_struct] = ffi.gc(my_struct.values, lib.free)
# AttributeError: free

1 Ответ

0 голосов
/ 16 марта 2019

Документы не забивают эту точку, но вам нужно выставить free как часть cdef вашей библиотеки, как и любую другую функцию, чтобы получить доступ к ней на стороне Python.Поместите void free(void *ptr); в вызов ffi.cdef, и функция free будет доступна через lib.free после компиляции:

from tempfile import TemporaryDirectory
from weakref import WeakKeyDictionary

from cffi import FFI

common_header = """
typedef struct {
  int32_t length;
  double* values;
} my_struct;
"""

# FFI
ffi = FFI()

ffi.cdef(common_header + """
int func(my_struct*);
void free(void *ptr); // <-- Key to lib.free working later
""")
ffi.set_source('_temp', common_header + """
int func(my_struct *input) {
  double* values = malloc(sizeof(double) * 3);
  input->length = 3;
  input->values = values;
  return 0;
}
""")

with TemporaryDirectory() as temp_dir:
    lib_path = ffi.compile(tmpdir=temp_dir)

    lib = ffi.dlopen(lib_path)

    func = lib.func

# Using the library
my_struct = ffi.new('my_struct*')
func(my_struct)

# Taking ownership of the malloced member
global_weakkey = WeakKeyDictionary()
global_weakkey[my_struct] = ffi.gc(my_struct.values, lib.free)
...