Конвертировать 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 или подобные функции, но, вероятно, ваши строки поддерживают индикатор длины, который вы можете использовать.