我有一个包装Win32 API函数WriteFile()
的类方法。此API函数对要写入的数据采用LPCVOID
参数。但相反,我想将C ++迭代器传递给它。我该怎么做?
WriteFile()
功能:
BOOL WINAPI WriteFile(
_In_ HANDLE hFile,
_In_ LPCVOID lpBuffer,
_In_ DWORD nNumberOfBytesToWrite,
_Out_opt_ LPDWORD lpNumberOfBytesWritten,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
我的实施:
template <class Iter>
BinaryFile::RETURN_VALUES BinaryFile::Write(
Iter Begin,
Iter End,
DWORD & dwNumberOfBytesWritten /*= DUMMY_DWORD_REFERENCE*/)
{
if (m_nFileState != STATE_OPEN) return WRITE_FILE_NOT_OPEN;
BOOL bResult = WriteFile((HANDLE) m_hFile,
(LPCVOID) Begin,
(DWORD) sizeof(*Begin) * (End - Begin),
(LPDWORD) &dwNumberOfBytesWritten,
(LPOVERLAPPED) NULL);
m_dwLastError = ::GetLastError();
m_FilePointer += dwNumberOfBytesWritten;
if (bResult)
return WRITE_SUCCESSFUL;
else
return WRITE_FAILURE;
}
尝试调用它:
TextFile::RETURN_VALUES TextFile::Write(std::vector<uint8_t> & String)
{
DWORD dwNumberOfBytesWritten;
BinaryFile::RETURN_VALUES WriteReturn = m_File.Write(
String.begin(),
String.end(),
dwNumberOfBytesWritten);
if (WriteReturn == BinaryFile::RETURN_VALUES::WRITE_SUCCESSFUL)
return WRITE_SUCCESSFUL;
else if (dwNumberOfBytesWritten < String.end() - String.begin())
return WRITE_NOT_ALL_WRITTEN;
else
return WRITE_FAILURE;
}
我得到的编译器(VS2012)错误:
BinaryFile.h
错误C2440
'type cast':无法转换为'std :: _ Vector_iterator&lt; _Myvec&gt;' 'LPCVOID'
答案 0 :(得分:3)
对于std:::vector<some POD type>
或std::string
这样的简单容器,您可以这样做:
template <class Iter>
BinaryFile::RETURN_VALUES BinaryFile::Write(
Iter Begin,
Iter End,
DWORD & dwNumberOfBytesWritten /*= DUMMY_DWORD_REFERENCE*/)
{
if (m_nFileState != STATE_OPEN)
return WRITE_FILE_NOT_OPEN;
BOOL bResult = WriteFile((HANDLE) m_hFile,
(LPCVOID) &*Begin,
(DWORD) sizeof(*Begin) * (End - Begin),
(LPDWORD) &dwNumberOfBytesWritten,
(LPOVERLAPPED) NULL);
m_dwLastError = ::GetLastError();
if (!bResult)
return WRITE_FAILURE;
m_FilePointer += dwNumberOfBytesWritten;
return WRITE_SUCCESSFUL;
}
但是对于更复杂的容器,例如std::list
,你必须这样做(这将适用于所有容器,但只要它们持有POD类型):
template <class Iter>
BinaryFile::RETURN_VALUES BinaryFile::Write(
Iter Begin,
Iter End,
DWORD & dwNumberOfBytesWritten /*= DUMMY_DWORD_REFERENCE*/)
{
dwNumberOfBytesWritten = 0;
if (m_nFileState != STATE_OPEN)
return WRITE_FILE_NOT_OPEN;
DWORD dwWritten;
while (Begin != End)
{
BOOL bResult = WriteFile((HANDLE) m_hFile,
(LPCVOID) &*Begin,
(DWORD) sizeof(*Begin),
(LPDWORD) &dwWritten,
(LPOVERLAPPED) NULL);
m_dwLastError = ::GetLastError();
if (!bResult)
return WRITE_FAILURE;
m_FilePointer += dwWritten;
dwNumberOfBytesWritten += dwWritten;
++Begin;
}
return WRITE_SUCCESSFUL;
}
在这种情况下,dwNumberOfBytesWritten
并没有那么有意义。将其更改为dwNumberOfItemsWritten
会更有意义,例如:
template <class Iter>
BinaryFile::RETURN_VALUES BinaryFile::Write(
Iter Begin,
Iter End,
DWORD & dwNumberOfItemsWritten /*= DUMMY_DWORD_REFERENCE*/)
{
dwNumberOfItemsWritten = 0;
if (m_nFileState != STATE_OPEN)
return WRITE_FILE_NOT_OPEN;
DWORD dwWritten;
while (Begin != End)
{
BOOL bResult = WriteFile((HANDLE) m_hFile,
(LPCVOID) &*Begin,
(DWORD) sizeof(*Begin),
(LPDWORD) &dwWritten,
(LPOVERLAPPED) NULL);
m_dwLastError = ::GetLastError();
if (!bResult)
return WRITE_FAILURE;
m_FilePointer += dwWritten;
++dwNumberOfItemsWritten;
++Begin;
}
return WRITE_SUCCESSFUL;
}
TextFile::RETURN_VALUES TextFile::Write(std::vector<uint8_t> & String)
{
DWORD dwNumberOfItemsWritten;
BinaryFile::RETURN_VALUES WriteReturn = m_File.Write(
String.begin(),
String.end(),
dwNumberOfItemsWritten);
if (WriteReturn == BinaryFile::RETURN_VALUES::WRITE_SUCCESSFUL)
return WRITE_SUCCESSFUL;
else if (dwNumberOfItemsWritten < String.size())
return WRITE_NOT_ALL_WRITTEN;
else
return WRITE_FAILURE;
}
最后,在任何一种情况下,都不要忘记WriteFile()
不能保证写入你请求的字节数,所以你真的应该在循环中调用它,直到所有预期的数据都被写入完全或直到发生错误,例如:
template <class Iter>
BinaryFile::RETURN_VALUES BinaryFile::Write(
Iter Begin,
Iter End,
DWORD & dwNumberOfItemsWritten /*= DUMMY_DWORD_REFERENCE*/)
{
dwNumberOfItemsWritten = 0;
if (m_nFileState != STATE_OPEN)
return WRITE_FILE_NOT_OPEN;
DWORD dwWritten;
while (Begin != End)
{
LPBYTE pData = (LPBYTE) &*Begin;
DWORD dwSize = sizeof(*Begin);
do
{
BOOL bResult = WriteFile((HANDLE) m_hFile,
(LPCVOID) pData,
(DWORD) dwSize,
(LPDWORD) &dwWritten,
(LPOVERLAPPED) NULL);
m_dwLastError = ::GetLastError();
if (!bResult)
return WRITE_FAILURE;
m_FilePointer += dwWritten;
pData += dwWritten;
dwSize -= dwWritten;
}
while (dwSize > 0);
++dwNumberOfItemsWritten;
++Begin;
}
return WRITE_SUCCESSFUL;
}
答案 1 :(得分:0)
你可以(甚至应该)将你的函数仅专门用于向量的迭代器和原始指针,并拒绝所有其他函数。如果是vector的迭代器,你可以传递给指针式函数&*Begin
,就像@chris所说的那样。我不确定,你能够为operator*
迭代器调用End
,但你可以尝试这个技巧:
auto e = End;
e--;
auto pe = &*e;
e++;
最后:你应该在功能开始时检查Begin != End