0

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
'型キャスト': 'std::_Vector_iterator<_Myvec>' から 'LPCVOID' に変換できません

4

2 に答える 2

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;
}
于 2013-05-17T04:04:40.990 に答える
0

関数をベクトルの反復子と生のポインターのみに特化し、他のすべてを拒否することができます (おそらくそうするべきです) 。&*Begin@chrisが言ったように、ベクトルのイテレータの場合、ポインタスタイルの関数に渡すことができます。イテレータを呼び出すことができるかどうかはわかりませんが、次のトリックを試すことができoperator*ます。End

auto e = End;
e--;
auto pe = &*e;
e++;

最後に:Begin != End関数の開始時に確認する必要があります

于 2013-05-17T04:05:55.910 に答える