我想将Haskell中的严格ByteStrings
转换为C ++的std::string
,以通过the FFI将其传递给C ++库。由于ByteString
可能包含NULL
个字符,因此转换为CString
作为中间步骤是不可行的。这里有什么正确的方法?
当前解决方案
感谢目前为止的答案。我希望为这项任务提供规范的解决方案,但也许它还不存在:)
string(const char * s,size_t n);
内容初始化为由s指向的字符数组中前n个字符组成的字符串副本。
因此可以编写一个从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)
然后,伴随toCCString_
的C ++代码看起来就像Neil和Alan指出的那样。
答案 0 :(得分:3)
输入CString = Ptr CChar
C字符串是对NUL终止的C字符数组的引用。
输入CStringLen =(Ptr CChar,Int)
具有显式长度信息的字符串,以字节为单位,而不是终止NUL(允许字符串中间的NUL字符)。
如果您使用CStringLen
,则应该没有问题。 (事实上,我建议这是因为interfacing C++ and Haskell is a nightmare。)
NULL
缓冲区中间的 char
字符只有在您不知道其中包含的数据应该多长时才会出现问题(因此必须遍历它)寻找NULL
,希望这是数据的预期结束。
答案 1 :(得分:2)
您的ByteString
(及其空值)是否实际上代表文本字符串?如果没有,那么std::vector<char>
会更合适。
话虽如此,std :: string的内部表示不依赖于null终止,因此你可以拥有一个带有空字符的std :: string。使用constructor with the prototype string(const char * s, size_t n)。只是不要依赖.c_str()来接口任何期望空终止的c字符串的东西。
答案 2 :(得分:0)
C ++字符串可以包含空字符。假设你有类似的东西:
char s1[] ="string containing nulls";
然后你可以转换为std :: string
string s2( s1, length_of_s1 );
问题是如何获得length_of_s1
- 显然你不能使用strlen或类似的函数,但可能你的字符串正在维护一个你可以使用的长度指示器。