Это часть приложения, предназначенного для обработки файлов и резервных копий. Моя цель - реализовать эту функцию, чтобы система могла быстрее копировать файлы.
Я наткнулся на очень полезный ответ на 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;
}
Изображение (если это вообще помогает)
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 компилируется сейчас