Преобразовать Haskell ByteStrings в С++ std::string

Я хочу преобразовать строгий ByteStrings из Haskell в std::string C++, чтобы передать его в библиотеку C++ через FFI. Поскольку ByteString может содержать NULL символов, преобразование в CString в качестве промежуточного шага нецелесообразно. Какой здесь правильный подход?

текущее решение

Спасибо за ответы. Я надеялся на каноническое решение этой задачи, но, возможно, его еще не существует :)

В некоторой документации по библиотеке C++ говорится следующее:

строка (const char * s, size_t n);

Содержимое инициализируется копией строки, состоящей из первых n символов в массиве символов, на который указывает s.

Поэтому можно написать такую ​​функцию, которая один раз копирует из ByteString для построения std::string

foreign import ccall unsafe toCCString_ :: CString -> CUInt -> IO (Ptr CCString)
toCCString :: ByteString -> IO (Ptr CCString)
toCCString bs =
    unsafeUseAsCStringLen bs $ \(cstring,len) ->
    toCCString_ cstring (fromIntegral len)

Тогда код C++, сопровождающий toCCString_, будет выглядеть так, как указали Нил и Алан.


person Long    schedule 26.05.2011    source источник
comment
Нам нужно намного больше информации о том, как вы собираетесь связать два языка.   -  person Lightness Races in Orbit    schedule 26.05.2011
comment
Я немного отредактировал свой вопрос, но я не уверен, какую информацию вы имеете в виду.   -  person Long    schedule 26.05.2011
comment
через FFI, что нам было нужно.   -  person Lightness Races in Orbit    schedule 26.05.2011
comment
Извините, что ранее редактировал CString. Не знал тогда, что это что-то конкретное. Вернулись.   -  person Lightness Races in Orbit    schedule 26.05.2011


Ответы (3)


документация великолепна!

тип CString = Ptr CChar

Строка C — это ссылка на массив символов C, оканчивающийся NUL.

тип CStringLen = (Ptr CChar, Int)

Строка с явной информацией о длине в байтах вместо завершающего NUL (допускаются символы NUL в середине строки).

Если вы используете CStringLen, у вас не должно возникнуть проблем. (На самом деле, я рекомендую это, потому что интерфейс C++ и Haskell — это кошмар.)

NULL символов в середине char буферов проблематичны только в том случае, если вы не знаете, какой длины данные, содержащиеся в них, должны быть (и, следовательно, вам приходится просматривать их в поисках NULL, надеясь, что это и есть предполагаемый конец данных).

person Lightness Races in Orbit    schedule 26.05.2011

Действительно ли ваш ByteString (с нулями) представляет собой текстовую строку? Если нет, то std::vector<char> будет более подходящим.

При этом внутреннее представление std::string не зависит от нулевого завершения, поэтому вы можете иметь std::string с нулевыми символами. Используйте конструктор с прототипом string(const char * s, size_t n). . Просто не полагайтесь на .c_str() для взаимодействия с чем-либо, ожидающим строку c с нулевым завершением.

person Alan    schedule 26.05.2011
comment
Вывод Binary или Cereal имеет заголовки, содержащие NULL, где это необходимо для указания размера следующих данных. Являются ли эти данные просто текстовыми данными, заранее не определено. - person Long; 27.05.2011
comment
@Long: Похоже, что std:vector лучше подходит для вашего использования. Существуют ли какие-либо фактические функции, специфичные для строк, которые вы используете в буфере? - person Alan; 27.05.2011
comment
Я пишу привязки к библиотеке поиска Xapian, и внутри она хранит любую определяемую пользователем дополнительную информацию (от простых строк до сложных структур данных) как std::string. Зная это, я предполагаю, что использование std::vector будет просто ненужным промежуточным шагом. - person Long; 27.05.2011

Строки C++ могут содержать нулевые символы. Предположим, у вас есть что-то вроде этого:

char s1[] ="string containing nulls";

то вы можете преобразовать в std::string

string s2( s1, length_of_s1 );

Проблема в том, как получить length_of_s1 - очевидно, вы не можете использовать strlen или подобные функции, но, предположительно, ваши строки поддерживают индикатор длины, который вы можете использовать.

person Community    schedule 26.05.2011
comment
Я не понимаю, как это каким-либо образом отвечает на вопрос. - person fuz; 26.05.2011