This is part of an application aimed at handling files & backups. My aim is to implement this function to allow the system to copy files faster.
I came across this very useful answer on SO suggesting how to implement the CopyFileExW / CopyFile2 in Qt.
The problem
using the code as posted runs perfectly, however attempting to modify it to fit into my application causes the following problem:
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);
^
I did not see any mention of a requirement for the LPPROGRESS_ROUTINE
callback to be static
, but I changed it to static (and commented out those offending lines), yet this problem persists (which I almost expected).
It appears the signatures match according, where DWORD === unsigned int
, LPVOID & HANDLE === *void
and where LPPROGRESS_ROUTINE suggests its definition can return a 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 ) {...}
How can I resolve this as I have absolutely no idea?
Summary of change(s):
- changed to non-static method
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);
- header change of copy method
void copyFile(QString m_src, QString m_dst);
Full (minimal) Code below:
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);
//...
}
and source
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;
}
Image (if it helps at all)
UPDATE
As per @RbMm's request, see below for 'static' impl and corresponding error.
Qt Compile Error:
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);
^
Full Code Example:
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);
//...
}
and source
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;
}
Taking a look at the error, it appears to require an int type (for the LPBOOL
). Is it possible for me to use a bool in any way?
UPDATE 2
A quick search helped me with this using the BOOL
datatype for bStopBackup
which can be found in minwindef.h
.
It compiles now