c++ - 如何将 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 === *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) {...}
我怎么能解决这个问题,因为我完全不知道?
变更摘要:
- 改为非静态方法
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
可以bStopBackup
在minwindef.h
.
它现在编译
解决方案
推荐阅读
- c++ - 查找 .txt 文件中的项目数
- postgresql - 如何以其他用户身份连接到数据库?
- angular - Angular `ng update @angular/...` 返回 `401 Unauthorized`
- c# - Akka.net .net 标准到 .net 核心思想 接待员
- amazon-web-services - aws 私有子网访问
- vb.net - 表单之间的启动画面
- python - 没有名为“glob2”的模块
- javascript - 你如何用winston捕捉`错误:ENOENT:没有这样的文件或目录`?
- node.js - Passport Facebook 身份验证返回未定义?
- vba - 字符串案例的不选择案例的案例