Как преобразовать DWORD в обратный вызов LPPROGRESS_ROUTINE для CopyFileExW? - PullRequest
2 голосов
/ 07 августа 2020

Это часть приложения, предназначенного для обработки файлов и резервных копий. Моя цель - реализовать эту функцию, чтобы система могла быстрее копировать файлы.

Я наткнулся на очень полезный ответ на SO, предлагающий, как реализовать CopyFileExW / CopyFile2 в Qt.

Проблема

с использованием кода в том виде, в котором он был опубликован работает отлично, однако при попытке изменить его на вписывается в мое приложение, вызывает следующую проблему:

path\to\project\...\libs\backupmanager.cpp:2806: error: cannot convert 'DWORD (BackupManager::*)(LARGE_INTEGER, LARGE_INTEGER, LARGE_INTEGER, LARGE_INTEGER, DWORD, DWORD, HANDLE, HANDLE, LPVOID) {aka long unsigned int (BackupManager::*)(_LARGE_INTEGER, _LARGE_INTEGER, _LARGE_INTEGER, _LARGE_INTEGER, long unsigned int, long unsigned int, void*, void*, void*)}' to 'LPPROGRESS_ROUTINE {aka long unsigned int (__attribute__((__stdcall__)) *)(_LARGE_INTEGER, _LARGE_INTEGER, _LARGE_INTEGER, _LARGE_INTEGER, long unsigned int, long unsigned int, void*, void*, void*)}' for argument '3' to 'WINBOOL CopyFileExW(LPCWSTR, LPCWSTR, LPPROGRESS_ROUTINE, LPVOID, LPBOOL, DWORD)'
                            &BackupManager::copyProgress, this, &bStopBackup, 0);
                                                                           ^

Я не видел никаких упоминаний о требовании для обратного вызова LPPROGRESS_ROUTINE быть static, но я изменил его на stati c (и закомментировал эти оскорбительные строки), но эта проблема сохраняется (чего я почти ожидал).

Похоже, что подписи совпадают, где DWORD === unsigned int, LPVOID & HANDLE === *void и где LPPROGRESS_ROUTINE предлагает его определение может возвращать DWORD.

LPPROGRESS_ROUTINE LpprogressRoutine;

DWORD LpprogressRoutine (LARGE_INTEGER TotalFileSize, LARGE_INTEGER TotalBytesTransferred, LARGE_INTEGER StreamSize, LARGE_INTEGER StreamBytesTransferred, DWORD dwStreamNumber, DWORD dwCallbackReason, HANDLE hSourceFile, HANDLE hDestinationFile, LPVOID lpData) {...}

Как я могу решить эту проблему, если я совершенно не знаю?

Сводка изменений:

  • изменено на нестатическое c метод
DWORD CALLBACK copyProgress(
      LARGE_INTEGER totalSize, LARGE_INTEGER totalTransferred,
      LARGE_INTEGER streamSize, LARGE_INTEGER streamTransferred,
      DWORD streamNo, DWORD callbackReason, HANDLE src, HANDLE dst,
      LPVOID data);
  • заголовок изменение метода копирования
void copyFile(QString m_src, QString m_dst);

Полный (минимальный) Код ниже:

class BackupManager : public QObject {
     Q_OBJECT

 private:
 QWaitCondition pauseThreadCondition;
 QMutex backupPauseLock;
 bool bPauseBackup = false, bStopBackup = false;

 static DWORD CALLBACK copyProgress(
      LARGE_INTEGER totalSize, LARGE_INTEGER totalTransferred,
      LARGE_INTEGER streamSize, LARGE_INTEGER streamTransferred,
      DWORD streamNo, DWORD callbackReason, HANDLE src, HANDLE dst,
      LPVOID data);

     void copyFile(QString m_src, QString m_dst);

  //...

  signals:
     void fileCopyFinished();
     void fileCopyFailed(QString error);
     void fileCopyProgress(qint64 progress, qint64 total);
  //...
}

и источник

void BackupManager::copyFile(QString m_src, QString m_dst)
{
     auto rc = CopyFileExW((LPCWSTR)m_src.utf16(), (LPCWSTR)m_dst.utf16(),
                           &BackupManager::copyProgress, this, &bStopBackup, 0);
     if (!rc)
          emit fileCopyFailed(getLastErrorMsg());
     emit fileCopyFinished();
}
DWORD CALLBACK BackupManager::copyProgress(
     const LARGE_INTEGER totalSize, const LARGE_INTEGER totalTransferred,
     LARGE_INTEGER, LARGE_INTEGER, DWORD,
     DWORD, HANDLE, HANDLE,
     LPVOID data)
{
     emit fileCopyProgress(totalTransferred.QuadPart, totalSize.QuadPart);
     if (bPauseBackup) {
          backupPauseLock.lock();
          pauseThreadCondition.wait(&backupPauseLock);
          backupPauseLock.unlock();
     }
     return PROGRESS_CONTINUE;
}

Изображение (если это вообще помогает)

enter image description here


UPDATE

As per @ RbMm запрос, см. Ниже для 'stati c' impl и соответствующую ошибку.

Ошибка компиляции Qt:

path\to\project\...\libs\backupmanager.cpp:2806: error: cannot convert 'bool*' to 'LPBOOL {aka int*}' for argument '5' to 'WINBOOL CopyFileExW(LPCWSTR, LPCWSTR, LPPROGRESS_ROUTINE, LPVOID, LPBOOL, DWORD)'
                            &BackupManager::copyProgress, this, &bStopBackup, 0);
                                                                               ^

введите описание изображения здесь

Пример полного кода:

 class BackupManager : public QObject {
     Q_OBJECT

 private:
 QWaitCondition pauseThreadCondition;
 QMutex backupPauseLock;
 bool bPauseBackup = false, bStopBackup = false;

 static DWORD CALLBACK copyProgress(
      LARGE_INTEGER totalSize, LARGE_INTEGER totalTransferred,
      LARGE_INTEGER streamSize, LARGE_INTEGER streamTransferred,
      DWORD streamNo, DWORD callbackReason, HANDLE src, HANDLE dst,
      LPVOID data);

     void copyFile(QString m_src, QString m_dst);

  //...

  signals:
     void fileCopyFinished();
     void fileCopyFailed(QString error);
     void fileCopyProgress(qint64 progress, qint64 total);
  //...
}

и источник

void BackupManager::copyFile(QString m_src, QString m_dst)
{
     auto rc = CopyFileExW((LPCWSTR)m_src.utf16(), (LPCWSTR)m_dst.utf16(),
                           &BackupManager::copyProgress, this, &bStopBackup, 0);
     if (!rc)
          emit fileCopyFailed(getLastErrorMsg());
     emit fileCopyFinished();
}
DWORD CALLBACK BackupManager::copyProgress(
     const LARGE_INTEGER totalSize, const LARGE_INTEGER totalTransferred,
     LARGE_INTEGER, LARGE_INTEGER, DWORD,
     DWORD, HANDLE, HANDLE,
     LPVOID data)
{
//     emit fileCopyProgress(totalTransferred.QuadPart, totalSize.QuadPart);
//     if (bPauseBackup) {
//          backupPauseLock.lock();
//          pauseThreadCondition.wait(&backupPauseLock);
//          backupPauseLock.unlock();
//     }
     return PROGRESS_CONTINUE;
}

Взглянув на ошибку, кажется, что требуется тип int (для LPBOOL). Могу ли я каким-либо образом использовать bool?

ОБНОВЛЕНИЕ 2

Быстрый поиск помог мне в этом, используя тип данных BOOL для bStopBackup, который можно найти в minwindef.h.

It компилируется сейчас

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...