首页 > 解决方案 > 如何将 DWORD 转换为 CopyFileExW 的 LPPROGRESS_ROUTINE 回调?

问题描述

这是旨在处理文件和备份的应用程序的一部分。我的目标是实现这个功能,让系统更快地复制文件。

我在 SO 上遇到了这个非常有用的答案,建议如何在 Qt中实现CopyFileExW / CopyFile2 。

问题

使用发布的代码可以完美运行,但是尝试修改它以适应我的应用程序会导致以下问题:

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,但我将其更改为静态(并注释掉那些有问题的行),但这个问题仍然存在(我几乎预料到了)。

看起来签名匹配,DWORD === unsigned int其中LPVOID & HANDLE === *voidLPPROGRESS_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) {...}

我怎么能解决这个问题,因为我完全不知道?


变更摘要:

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;
}

图片(如果有帮助的话)

在此处输入图像描述


更新

根据@ RbMm的要求,请参阅下面的“静态” 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)。我可以以任何方式使用布尔值吗?


更新 2

使用BOOL可以bStopBackupminwindef.h.

它现在编译

标签: c++windowsqtfile-copying

解决方案


推荐阅读