Как Python может получить двоичные данные (char *) из C ++ с помощью SWIG? - PullRequest
4 голосов
/ 17 ноября 2011

Я использую функции C ++ в Python от SWIG, и теперь я столкнулся с проблемой. Когда я передаю char * из C ++ в Python, char * обрезается Python.

Например:

example.h:

char * fun()
{
    return "abc\0de";
}

сейчас в Python, мы называем example.fun () это только печать «А» вместо "А \ 0de" данные за '\ 0' удаляются Python.

Я хочу получить все символы (это двоичные данные, которые могут содержать '\ 0') из fun () в C ++, и любые советы приветствуются

Ответы [ 3 ]

8 голосов
/ 17 мая 2012

Прежде всего, вам не следует использовать char *, если вы имеете дело с двоичными данными (swig считает, что они являются обычными строками). Вместо этого вы должны использовать void *. Swig предоставляет модуль с именем «cdata.i» - Вы должны включить это в файл определения интерфейса.

Как только вы включите это, он дает две функции - cdata() и memmove().

  • Учитывая void * и длину двоичных данных, cdata() преобразует их в строковый тип целевого языка.
  • memmove() делает наоборот - учитывая тип строки, он копирует содержимое строки (включая встроенные нулевые байты) в тип C void*.

Обработка двоичных данных становится намного проще с этим модулем. Я надеюсь, что это то, что вам нужно.

example.i
%module example
%include "cdata.i"
%{
void *fun()
{
        return "abc\0de";
}
%}

test.py
import example
print example.cdata(example.fun(), 6)
6 голосов
/ 17 ноября 2011
Строки

C / C ++ заканчиваются на NULL, что означает, что первый символ \0 обозначает конец строки.

Когда функция возвращает указатель на такую ​​строку, вызывающая сторона (в данном случае SWIG) не может узнать, есть ли больше данных после первого \0, поэтому вы получаете только первую часть.

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

void fun(char** s, int *sz)
{
    *s = "abc\0de";
    *sz = 6;
}

Документы SWIG предлагают использовать cstring.i библиотеку для переноса таких функций. В частности, последний макрос делает именно то, что вам нужно.

%cstring_output_allocate_size(parm, szparm, release)

Прочитайте документы , чтобы узнать, как его использовать.

0 голосов
/ 17 ноября 2011

См. 8.3 C Обработка строк в документации.

Также из документации :

Тип данных char * обрабатываетсяв виде строки ASCII с нулевым символом в конце.SWIG отображает это в 8-битную символьную строку на целевом языке сценариев.SWIG преобразует символьные строки на целевом языке в NULL-завершенные строки перед передачей их в C / C ++.Обработка этих строк по умолчанию не позволяет им иметь встроенные байты NULL.Поэтому тип char * обычно не подходит для передачи двоичных данных.Однако это поведение можно изменить, определив карту типов SWIG.Подробнее об этом см. Главу о картах типов.

...