Конвертировать Haskell ByteStrings в C ++ std :: string - PullRequest
2 голосов
/ 26 мая 2011

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

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

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

Некоторая документация библиотеки c ++ гласит следующее:

string (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 ]

3 голосов
/ 26 мая 2011

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

type CString = Ptr CChar

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

тип CStringLen = (Ptr CChar, Int)

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

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

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

2 голосов
/ 26 мая 2011

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

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

0 голосов
/ 26 мая 2011

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

char s1[] ="string containing nulls";

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

string s2( s1, length_of_s1 );

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

...