为C库编写C ++包装器。在库中有一个函数接受缓冲区unsigned char *
。自从使用C ++以来,我将我的实际缓冲区存储在std::vector<char>
中,而且,在包装器类中我还添加了const
,因为所讨论的缓冲区是一个输入缓冲区,它不会被修改。但是我的代码没有编译,演示:
#include <stdio.h>
#include <vector>
void x(unsigned char *s)
{
printf("%s\n", s);
}
int main()
{
const std::vector<char> s(10);
x(reinterpret_cast<unsigned char *>(s.data())); // FAILS
}
id有什么问题?如果我从consts
移除const std::vector<char> s(10);
它可以正常工作,但我更喜欢这样。
答案 0 :(得分:7)
您必须const_cast
删除常量,然后reinterpret_cast
将char *
投射到unsigned char *
试试这个:x(reinterpret_cast<unsigned char*>(const_cast<char *>(s.data())));
注意:但是请记住,const_cast
只有在您投射最初为非const的变量时才是安全的。请参阅this回答。
答案 1 :(得分:1)
您的错误是因为您将std::vector
声明为const
。
如果删除常量,它可以正常工作。 (见here)
无论如何,您应该问自己是否真的需要在阵列中存储char
或unsigned char
。
如果你想保留const
,你必须使用const_cast
,但你的行会变得很长:
x(const_cast<unsigned char*>(reinterpret_cast<const unsigned char *>(s.data())));
如果您有权访问该库,最好将缓冲区标记为const
(如果未更改)。
但是,因为它不是const
,你不能确定它不会被函数修改,因此,你不应该将你的std::vector
保持为{{1} }}
答案 2 :(得分:0)
分享我的经验,因为我在跨平台实施期间也遇到了同样的问题。上述方法在Windows和Linux(Redhat)上运行良好,但在Solaris 10和IBM AIX上没有。
Solaris 10使用上述建议的方法提供以下错误。
'nofieldident: data is not a member of const std::vector<unsigned char>'
这是一种使用矢量数据'const'
的方法,它可以在Windows,Linux,Solaris上运行
#include <iostream>
#include <vector>
using namespace std;
/// Data Interface, which is visible to the outside
class IDataInterface {
public:
// Get the underlying data as a const data pointer
virtual const unsigned char* Data(size_t& nSize) = 0;
};
/// Implemetation of the IDataInterface
class CData : public IDataInterface {
public:
// Constructor
CData(vector<unsigned char> data);
// Overriden function of the interface
const unsigned char* Data(size_t& nSize);
private:
/// Actual data member
vector<unsigned char> m_vData;
};
/// Constructor implementation
CData::CData(vector<unsigned char> vData) {
// resize to the input data size
m_vData.resize(vData.size());
// Copy the data
memcpy(&m_vData[0], &vData[0], vData.size());
}
/// Implementation of the data function
const unsigned char* CData::Data(size_t& nSize /**< Size of data returned */) {
/*
* Following four methods worked fine on Windows, RedHat, but Failed on Solaris 10 and IBM AIX
*/
// return &m_vData[0];
// return m_vData.data();
// return const_cast<unsigned char*>(reinterpret_cast<const unsigned char *>(m_vData.data()));
// return reinterpret_cast<unsigned char*>(const_cast<unsigned char *>(m_vData.data()));
/* This was tested on following and works fine.
* Windows (Tested on 2008 to 2016, 32/64 bit, R2 versions)
* RedHat 5&7 (32/64 bit)
* Solaris 10 (32/64 bit)
* IBM AIX 7.10
*
*/
return &m_vData.front(); --> This works on windows, redhat, solaris 10, aix
}
/// Main class
int main() {
// Vector of data
vector<unsigned char> vData;
// Add data onto the vector
vData.push_back('a');
vData.push_back('b');
vData.push_back('c');
// Create an instance from the vector of data given
CData oData(vData);
// Get the data from the instance
size_t nSize(0);
cout << "Data:" << oData.Data(nSize) << endl;
return 0;
}
Output:
Data:abc