передать Python str в функцию C - PullRequest
2 голосов
/ 26 февраля 2012

У меня есть libx.so, и он экспортирует функцию и глобальные char *,

char *c_ptr = 0;

void foo(char *s)
{
    c_ptr = s;
}

В Python я передаю str в foo двумя способами,

>>>libx = ctypes.CDLL("./libx.so")
#pass a raw str
>>>libx.foo("string")

#pass a c_char_p object
>>>libx.foo(c_char_p("strng"))

Q

1. Я думаю, libx.foo("string") передает объект Python str в функцию C, которая позже присвоит строку char *c_ptr.Интересно, c_ptr будет ли указывать на str объект "string" после вызова foo?Потому что я полагаю, что str объект "string" будет собирать мусор после вызова foo, верно?

2. Разница между двумя способами (прохождение "string" и c_char_p("string"))эффект?Отличаются ли они по сути?

Ответы [ 2 ]

4 голосов
/ 06 марта 2012

1: что происходит

ctypes адаптирует строку Python, правильно предполагая, что функция принимает char*. Фактически, libx.foo("string") эквивалентен второму примеру libx.foo(c_char_p("string")) с небольшой адаптацией во время выполнения.

Ваша интуиция о том, что строка является сборщиком мусора вскоре после вызова, верна. Ничто в Python не сохраняет ссылку на адаптированное представление строки c_char_p, и, таким образом, оно будет возвращено в пул объектов - вероятно, будет переиздано в будущем. Это означает, что char* c_ptr, вероятно, очень скоро укажет на мусор.

2: разные по своему действию

Вторая форма позволяет вам сохранить ссылку на представление, переданное в функцию C. Если вы немного изменили пример:

>>> s = c_char_p("string")
>>> libx.foo(s)

Тогда, пока ссылка поддерживается на s, значение c_ptr будет действительным. Это можно сделать, просто сохранив ссылку в модуле, реализующем привязку к libx.

0 голосов
/ 17 июня 2019

Для тех, кто находит это, в Python 3 строка и байты теперь разные.Для ctypes требуется экземпляр байта, чтобы правильно передать параметр, так как char*.

test_lib.get_val(b'Test1', byref(a)) передаст полный «Test1» в виде char * в функцию c

test_lib.get_val('Test1', byref(a))не будет передавать 'Test1' как символ *, из моего небольшого тестирования он пропускает первую букву питона str, за которой следует нулевая буква.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...