2

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

当前解决方案

感谢您到目前为止的答案。我希望该任务有一个规范的解决方案,但也许它还不存在:)

一些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)

随之而来的 C++ 代码toCCString_看起来就像 Neil 和 Alan 指出的那样。

4

3 回答 3

3

文档很棒!

类型 CString = Ptr CChar

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

类型 CStringLen = (Ptr CChar, Int)

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

如果你使用 a CStringLen,你应该没有问题。(事实上​​,我推荐这个,因为连接 C++ 和 Haskell 是一场噩梦。)

NULL缓冲区中间的字符char只有在您不知道其中包含的数据应该有多长时才会出现问题(因此必须遍历它以寻找 a NULL,希望那是数据的预期结束)。

于 2011-05-26T15:22:45.713 回答
2

你的ByteString(带有它的空值)实际上代表一个文本字符串吗?如果没有,那就std::vector<char>更合适了。

That being said, the internal representation of std::string does not depend on null termination so you can have a std::string with null characters in it. Use the constructor with the prototype string(const char * s, size_t n). Just don't depend on .c_str() to interface with anything expecting a null terminated c string.

于 2011-05-26T15:25:35.407 回答
0

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

char s1[] ="string containing nulls";

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

string s2( s1, length_of_s1 );

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

于 2011-05-26T14:39:46.613 回答