将Haskell ByteStrings转换为C++std::string
Convert Haskell ByteStrings to C++ std::string
我想将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或类似的函数,但可能你的字符串维护了一个可以使用的长度指示器。
- cppcheck在const std::string[]上引发警告
- 将std::string传递给WriteConsole API
- 为std::string的某个索引赋值
- 使用 std::string () const 函数启动线程或未来
- 当我们进行一些操作时,应该使用什么'std::string'或'std::stringstream'?
- 如何更改大小(std::string)
- std::string 的对象真的可以移动吗?
- SegFault 同时使用 std::string::operator+= 和函数作为参数
- 无法从 std::string 中提取C++ Unicode 符号
- std::string 构造函数如何处理固定大小的 char[]?
- 真的没有来自 std::string_view 的 std::string 的显式构造函数吗?
- 将C++ std::string 转换为 UTF-16-LE 编码的字符串
- 重载 + 自己的类和 std::string 的运算符
- 如何使用 std::string 作为 QHash 的键?
- 将日语 wstring 转换为 std::string
- 可以从std::string继承以提供类型一致性吗
- 构造函数采用std::string_view与std::string并移动
- 在共享缓冲区内存中创建 ::std::string 对象
- std::string.size() 未知行为
- Valgrind 在 std::string::swap 中报告 SIGILL