将 Haskell ByteString 转换为 C++标准::字符串
我想将 Haskell 中的严格 ByteStrings
转换为 C++ 的 std::string
,通过 FFI。由于 ByteString
可能包含 NULL
字符,因此转换为 CString
作为中间步骤是不可行的。这里正确的方法是什么?
当前解决方案
感谢您迄今为止的回答。我希望为该任务找到一个规范的解决方案,但也许它还不存在:)
一些 c++ 库文档 内容如下:
字符串(const char * s, size_t n);
Content 被初始化为由 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 指出的那样。
I want to convert strict ByteStrings
from Haskell into C++'s std::string
to pass it to a C++ library via the FFI. As the ByteString
may contain NULL
characters, converting into a CString
as an intermediate step is not viable. What is the right approach here?
current solution
Thanks for the answers so far. I hoped for a canonical solution for that task, but maybe it does not exist yet :)
Some c++ library documentation says following:
string ( const char * s, size_t n );
Content is initialized to a copy of the string formed by the first n characters in the array of characters pointed by s.
Therefore one can write such a function which copies once from the ByteString to construct a 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)
The C++ code accompanying toCCString_
then would just look like Neil and Alan pointed out.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
文档很棒!
如果您使用
CStringLen
,则应该没有问题。 (事实上,我推荐这样做是因为 C++ 和 Haskell 的接口是一场噩梦。)仅当您不知道其中包含的数据应该有多长(因此必须遍历它)时,
字符才会出现问题寻找char
缓冲区中间的 NULLNULL
,希望这是数据的预期结尾)。The documentation is great!
If you use a
CStringLen
, you should have no problems. (In fact, I recommend this because interfacing C++ and Haskell is a nightmare.)NULL
characters in the middle ofchar
buffers is only problematic when you don't know how long the data contained therein should be (and thus have to traverse it looking for aNULL
, hoping that that's the intended end of the data).您的
ByteString
(及其空值)实际上代表文本字符串吗?如果没有,那么std::vector
会更合适。话虽这么说, std::string 的内部表示不依赖于 null 终止,因此您可以拥有一个包含 null 字符的 std::string 。使用带有原型 string(const char * s, size_t n) 的构造函数 。只是不要依赖 .c_str() 来与任何期望以 null 结尾的 c 字符串进行交互。
Does your
ByteString
(with its nulls) actually represent a text string? If not, thenstd::vector<char>
would be more appropriate.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.
C++ 字符串可以包含空字符。假设你有这样的东西:
那么你可以转换为 std::string
问题是如何获取 length_of_s1 - 显然你不能使用 strlen 或类似的函数,但大概你的字符串正在维护您可以使用的长度指示器。
C++ strings can contain null characters. Assuming you have something like this:
then you can convert to a std::string
The problem is how to get
length_of_s1
- obviously you can't use strlen, or similar functions, but presumably your strings are maintaining a length indicator you can use.