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

Convert Haskell ByteStrings to C++ std::string

本文关键字:C++std string 转换 Haskell ByteStrings      更新时间:2023-10-16

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

当前解决方案

谢谢你到目前为止的回答。我希望能为这项任务找到一个规范的解决方案,但也许它还不存在:)

一些c++库文档说明如下:

字符串(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指出的那样。

文档很棒!

类型CString=Ptr CChar

C字符串是对以NUL结尾的C字符数组的引用。

类型CStringLen=(Ptr CChar,Int)

具有以字节为单位的显式长度信息的字符串,而不是终止的NUL(允许在字符串中间使用NUL字符)。

如果您使用CStringLen,应该不会有任何问题。(事实上,我建议这样做,因为C++和Haskell的接口是一场噩梦。)

只有当您不知道中包含的数据应该多长时,char缓冲区中间的NULL字符才有问题(因此必须遍历它以查找NULL,希望这是数据的预期结尾)。

您的ByteString(及其null)实际上代表一个文本字符串吗?如果不是,则std::vector<char>将更合适。

也就是说,std::string的内部表示不依赖于null终止,因此可以有一个包含null字符的std::string。请将构造函数与原型字符串(const char*s,size_t n)一起使用。只是不要依赖.c_str()与任何期望以null结尾的c字符串进行接口。

C++字符串可以包含空字符。假设你有这样的东西:

char s1[] ="string containing nulls";

然后您可以转换为std::string

string s2( s1, length_of_s1 );

问题是如何获得length_of_s1——显然你不能使用strlen或类似的函数,但可能你的字符串维护了一个可以使用的长度指示器。