Как проверить равенство указателей в типах ctypes Python?

#python #ctypes #ffi

Вопрос:

Если у меня есть следующая библиотека C

 #include <stdint.h>

int64_t* foo(int64_t *x) {
    return x;
}
 

и я вызываю функцию из типов ctypes Python следующим образом:

 ptr = (ctypes.c_int64 * 100)()
rval = api.foo(ptr)
 

Наивно я бы предположил , что могу просто assertEqual(rval, ptr) , но это не удается. Печать rval и ptr соответственно я получаю

 <reference_project.LP_c_longlong object at 0x0000021A563BBDC0>
<tests.c_longlong_Array_100 object at 0x0000021A563BBF40>
 

Как я могу сравнить ptr и rval для равенства с Python?

Комментарии:

1. Я ожидал, что это сработает, если вы исправите типы, но нет. Похоже, что в ctypes просто нет сравнения указателей.

2. На самом деле, похоже, что ctypes вообще не реализует никаких операций сравнения для любых типов.

3. (В «исправьте типы» я включал преобразование ptr в фактический указатель — в настоящее время это массив. actual_ptr = ctypes.cast(ptr, ctypes.POINTER(ctypes.c_int64)) выполнит это преобразование.)

4. Исправлен пример; Я допустил ошибку, когда упрощал свой код для SO.

Ответ №1:

Отвечая на мой собственный вопрос, приведение указателей c_void_p и взятие .value , похоже, делают свою работу:

 ptr_via_void = ctypes.cast(ptr, ctypes.c_void_p).value
rval_via_void = ctypes.cast(rval, ctypes.c_void_p).value

print(ptr_via_void)  # 2373661818336
print(rval_via_void) # 2373661818336

assertEqual(ptr_via_void, rval_via_void)
 

Однако просто опустить .value не работает:

 ptr_via_void = ctypes.cast(ptr, ctypes.c_void_p)
rval_via_void = ctypes.cast(rval, ctypes.c_void_p)

print(ptr_via_void)  # c_void_p(1988667444176)
print(rval_via_void) # c_void_p(1988667444176)

# Although both print the same value, this FAILS:
assertEqual(ptr_via_void, rval_via_void)
 

Я не могу поверить, что, по-видимому, нет лучшего способа.

Комментарии:

1. Даже c_int(1) == c_int(1) возвращается False , но c_int(1).value == c_int(1).value возвращается True .