Как лучше всего вернуть строку в интерфейс Python SWIG?

Что представляет собой потокобезопасный способ без утечки памяти для возврата строки из C ++ в интерфейс python SWIG?

SWIG автоматически скопирует содержимое возвращаемого значения char * в строку Python. В этом руководстве по SWIG приведен пример:

char *__str__() {
    static char temp[256];
    /* WRITE STUFF TO STRING */
    return &temp[0];
}

В их примере в качестве возвращаемого значения используется статическая строка, но если моя программа на C ++ имеет несколько потоков, они могут легко перезаписать строки друг друга.

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

Единственное, о чем я могу думать, - это зарегистрировать и вернуть указатель на фактический строковый объект python (таким образом, сборщик мусора python позаботится об этом), но я не уверен, как это сделать, и мне интересно, есть ли более простой способ.


person Matt    schedule 07.07.2014    source источник
comment
А как насчет проверенного и надежного метода, когда вызывающий объект предоставляет буфер, а код C ++ просто копируется в этот буфер? Так, например, Windows API обрабатывает строки.   -  person PaulMcKenzie    schedule 07.07.2014
comment
@PaulMcKenzie Я не думаю, что это сработает со SWIG. Прежде всего, SWIG сможет предоставить указатель только на необработанные данные неизменяемой строки Python, что приведет к сбою Python при изменении. Во-вторых, это нарушит интерфейс таких методов, как __str__, которым не должны передаваться аргументы.   -  person Matt    schedule 07.07.2014
comment
Вы пробовали создать оболочку, возвращающую std :: string?   -  person Oliver    schedule 07.07.2014
comment
@Schollii Я пробовал, но SWIG конвертирует std::strings в строки Python.   -  person Matt    schedule 07.07.2014
comment
@Matt - I don't think that would work with SWIG. First of all, SWIG would only be able to supply a pointer to the raw data of an immutable python string Тогда в SWIG сильно не хватает функциональности, если нет возможности передать модифицируемый буфер функции. Second of all, that would violate the interface of methods such as __str__, which are not supposed to have any arguments passed to them Тогда, возможно, вам следует написать фабричный класс C ++, который выделяет и возвращает строки.   -  person PaulMcKenzie    schedule 07.07.2014
comment
@PaulMcKenzie Причина, по которой я задаю этот вопрос, - для людей, которые используют SWIG, которые столкнулись с этой проблемой, чтобы поделиться тем, как они ее решили. Кто угодно может найти временный обходной путь, я просто надеюсь, что мне не придется этого делать.   -  person Matt    schedule 07.07.2014
comment
@Matt, вы имели в виду ... но SWIG не конвертирует, верно? Прошло некоторое время, но я совершенно уверен, что это так, но вам нужно включить std::string карты типов.   -  person Oliver    schedule 07.07.2014
comment
@Schollii Да, я имел в виду именно это, извините за опечатку. Кстати, вы должны дать ответ на вопрос.   -  person Matt    schedule 08.07.2014


Ответы (1)


SWIG создает код оболочки для преобразования между строками C ++ std::string и Python, если вы включаете карты типов, определенные в std_string.i.

person Oliver    schedule 08.07.2014
comment
Спасибо! Я сделал %include <std_string.i>, и это сработало! - person Matt; 08.07.2014
comment
Освобождает ли это std :: string, если она была создана в методе C ++? Или нужно указать% new_object в методе C ++? - person Jason; 06.03.2015
comment
@jason Нужен newobj, но не уверен, выполните параллельное сравнение сгенерированного кода с объявлением newobj и без него, должно отображаться только несколько строк. - person Oliver; 07.03.2015
comment
Итак, ответ на мой комментарий заключается в том, что если std::string создается с new, то его нужно удалить вручную, и swig сделает это с %newobject. Но если std::string создается с объявлением типа std::string myStr, тогда C ++ обрабатывает его срок службы, и %newobject не повлияет на сгенерированный код. - person Jason; 07.03.2015