Конвертировать Haskell ByteStrings в C++ std::string

Я хочу преобразовать строгий ByteStrings из Haskell в C++ std::string передать его в библиотеку 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_ тогда бы просто выглядел, как указали Нейл и Алан.

3 ответа

Решение

Документация отличная!

Тип CString = Ptr CChar

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

Тип CStringLen = (Ptr CChar, Int)

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

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

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

Ваш ByteString (с его нулями) фактически представляет текстовую строку? Если нет то std::vector<char> было бы более уместным.

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

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

char s1[] ="string containing nulls";

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

string s2( s1, length_of_s1 );

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

Другие вопросы по тегам