C++ кодиране на знаци при конвертиране от низ към const char* за Ruby FFI интерфейс

Използвам външна библиотека на C++, която осъществява някаква HTTPS комуникация и предоставя отговора на XML сървъра. От страна на сървъра отговорът е кодиран чрез ISO-8859-15 и получавам std::string, който представлява този отговор извън API. Когато го разпечатам/запиша във файл, изглежда правилно.

Кодът за грешка std::string и int трябва да бъде предаден на моя външен повикващ. Така че връщам и двете стойности вътре в структура:

extern "C" {
  struct FoobarResponse {
    const char* responseText;
    int returnCode;
  };
}

За съжаление трябва да конвертирам std::string отговора в const char* низово представяне в стил C с помощта на std::c_str() преди. Причина: Моят повикващ е Ruby скрипт, който използва Ruby FFI за комуникация с моята C++ lib, а междуезичното преобразуване на типа тук е Ruby::string -> C::const char*.

Интересно тук: Ако аз std::cout конвертирания низ, след като съм го поставил в структурата, той все още е наред.

Проблемът: При обработка на отговора на сървъра от страна на Ruby, той е повреден. Вместо оригиналния отговор като:

<?xml version="1.0" encoding="ISO-8859-15"?>
<Foobar xmlns="http://www.foobar.com/2012/XMLSchema">
  ...
</Foobar>

Получавам низ, очевидно съдържащ непечатаеми знаци, който винаги е прекъснат в началото и в края.

?O[
l version="1.0" encoding="ISO-8859-15"?>
<Foobar xmlns="http://www.foobar.com/2012/XMLSchema">
</Fo??

Всъщност низът съдържа най-малко нови линии, връщане на каретка и раздели, може би повече.

Опитах да :force_encoding низа от страната на Ruby като ASCII-8BIT, ISO-8859-15 и UTF-8, без промяна. Опитах се да кодирам base64 от страната на C++, преди да поставя низа в структурата и да декодирам base64 от страната на Ruby, използвайки този код, без промяна.

Имах безброй опити да конвертирам низа, използвайки също Iconv, без промяна.

Също така се опитах да премахна непечатаеми знаци от низа, преди да го поставя в структурата, но не успях.

Нямам представа какво става тук и изчерпвам опциите. Може ли някой да ме насочи в правилната посока?

Поздрави Феликс


person GeorgieF    schedule 30.07.2013    source източник


Отговори (1)


Стойността, върната от c_str(), се унищожава веднага щом std::string излезе извън обхвата. Ако възнамерявате да предадете тази стойност на вашия скрипт, трябва да разпределите памет и да копирате низа в новоразпределеното пространство. Вижте този пример: http://www.cplusplus.com/reference/string/string/c_str/

Трябва също така да се уверите, че ruby ​​скриптът ще освободи правилно паметта.

Мисля, че това е обясненото там: https://github.com/ffi/ffi/wiki/Examples .

Пример със структура, предадена на Ruby от C: https://github.com/ffi/ffi/wiki/Examples#-structs

person fjardon    schedule 30.07.2013
comment
Не предавам низове от C към Ruby. Използвам структурата, спомената по-горе. Структурата е създадена от моята C библиотека и паметта, използвана от структурата, също се освобождава след това. От страна на Ruby отразявам структурата и имам достъп до нея. Низовете в структурата са достъпни. Те са само деформирани. Ако паметта беше унищожена твърде рано, нямаше да имам достъп до низа в Ruby, нали? - person GeorgieF; 30.07.2013
comment
Но вашата структура съдържа char* член. Трябва да разпределите паметта за това char* и да копирате c_str() в това новоразпределено пространство. Трябва също така да освободите тази памет ПРЕДИ да освободите паметта за вашата структура. - person fjardon; 30.07.2013
comment
Ще имате достъп до паметта, но тя ще бъде пълна с боклук. Точно това виждате. - person fjardon; 30.07.2013
comment
Чувствам се като глупак, какъвто съм. Не разпределих памет за низовете в структурата. Работи сега. Thx @fjardon, гласувам за. - person GeorgieF; 30.07.2013