将Haskell ByteStrings转换为C ++ std :: string

时间:2011-05-26 14:35:29

标签: c++ string haskell ffi

我想将Haskell中的严格ByteStrings转换为C ++的std::string,以通过the FFI将其传递给C ++库。由于ByteString可能包含NULL个字符,因此转换为CString作为中间步骤是不可行的。这里有什么正确的方法?

当前解决方案

感谢目前为止的答案。我希望为这项任务提供规范的解决方案,但也许它还不存在:)

有些c++ library documentation说:

  

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指出的那样。

3 个答案:

答案 0 :(得分:3)

documentation很棒!

  

输入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或类似的函数,但可能你的字符串正在维护一个你可以使用的长度指示器。