LINUX.ORG.RU

[Python] Собственный модуль и SWIG, помогите разобраться

 


0

1

В общем есть функция написанная на Си, размер возвращаемого буфера - 16 байт:

unsigned char *foo(unsigned char *str)
{
  ...
  return result;
}

Файл для SWIG'a выглядит вот так:

%module mymodule

extern char* decode();

В итоге после компиляции библиотеки получаю:

>>> import mymodule
>>> c=mymodule.foo("ABCDEFGH")
>>> len(c)
4

Хотя байты получаемые байты совпадают с требуемым результатом. ЧЯДНТ?

http://a-iv.ru/pyart/cpp2py.pdf

Вообще то так делать нельзя (кто чистит память после возврата char* и где вообще лежит результат ?)

Но - если там и правда 16 байт, должно быть 16 байт, если пишет 4байта значит там 4 байта до нуля. Проблемы в С.

AIv ★★★★★
()

>unsigned char *foo(unsigned char *str)
почему unsigned char?
А здесь >extern char< просто char ?
И вообще непонятно, что эти функции делают?
Напиши подробнее.

Bad_ptr ★★★★★
()
Ответ на: комментарий от AIv

> Вообще то так делать нельзя (кто чистит память после возврата char* и где вообще лежит результат ?)

В принципе нельзя. В документации к SWIG тоже рекомендуют использовать что-то типа

void foo1(const char *input, char *output, int len_output);

если надо обеспечить доступ к элементам массива output или это не строка С-формата. Если же надо просто вернуть строку, то в принципе можно как

const char *foo2(const char *input)

тогда с удалением памяти все хорошо — за это отвечает сама функция foo2.

abalakin ★★
()
Ответ на: комментарий от abalakin

Если ф-я для вызова чисто из питона, я обычно создавал и возвращал питоновскую строку, дальше уж это это питоновского сборщика мусора заботы.

AIv ★★★★★
()
Ответ на: комментарий от abalakin

> const char *foo2(const char *input)

тогда с удалением памяти все хорошо — за это отвечает сама функция foo2.

Вот тут подробней, я не понял. Мне всегда казалось, что если строка создана на стеке ф-ии, то ее при выходе из ф-ии должно убить. Если она конст, то происходит копирование?

AIv ★★★★★
()
Ответ на: комментарий от AIv

Хмм, если делать интерфейс только для питона, то да. SWIG же позволяет делать интерфейс разом для кучи языков, и питон только один из них.

abalakin ★★
()
Ответ на: комментарий от AIv

>> const char *foo2(const char *input)

тогда с удалением памяти все хорошо — за это отвечает сама функция foo2.

Вот тут подробней, я не понял. Мне всегда казалось, что если строка создана на стеке ф-ии, то ее при выходе из ф-ии должно убить. Если она конст, то происходит копирование?

Причем это? Возвращается указатель на какую-то внутреннюю область (локальную static, глобальный массив или массив в структуре/классе). Указатель прибивать не надо ;). А о прибивании внутреннего массива заботится сама функция/библиотека.

Вся идея SWIG, что не надо создавать массивы (строки) внутри функции и возвращать их. Этим должен заниматься вызывающий. Поэтому либо указатель + число элементов в аргументах, либо возвращать указатель на const, либо возвращать структуру (или указатель на нее) содержащую массив. Из последних SWIG хорошо понимает вроде только const char* (ожидает что это строка с 0x0 на конце).

abalakin ★★
()
Ответ на: комментарий от abalakin

А, точно, я ж читал про это в их доках, и даже местами использовал для разадресации указателей. Там вроде все на таких правилах построено.

AIv ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.