C++ DLL, которая может информировать вызывающую программу о ее прогрессе

Мой начальник хочет, чтобы я написал DLL на C++ (MSVC++2010), которая может выполнять теневое копирование тома, которое он может вызывать из VB6 (или на более позднем этапе, на других языках) и которое может возвращать обновления статуса, пока оно не закончено, Он называет это "события".

У меня такое чувство, что мне, наконец, нужно изучать COM (я бы предпочел не...) ... также, мне приходит в голову функция обратного вызова, но, конечно, невозможно передать указатели функций из VB6 в C++?

Может кто-нибудь описать, что я должен изучить и как это можно сделать, с или без COM?

РЕДАКТИРОВАТЬ: чтобы ответить на вопрос, рабочий поток должен быть:

  1. Приложение VB6 определяет файлы для резервного копирования

  2. Мне дан путь и я создаю временную теневую копию тома, которая включает этот путь и возвращает точку монтирования (или аналогичную)

    • на этом этапе я регулярно говорю приложению VB6, как далеко я нахожусь

  3. Приложение VB6 делает резервную копию теневой копии, а затем удаляет теневую копию.

6 ответов

Решение

Вы можете передать указатель на функцию "Отображение прогресса" из приложения VB в приложение C++ DLL, используя AddressOf оператор:

Declare Function CallMyDll ...

Sub DisplayStatus(ByVal SomeParameter As Long)
    ' ...
End SUb

Sub DoSomething()
    Call CallMyDll(AddressOf DisplayStatus)
End Sub

Некоторые не очень очевидные ошибки:

  1. Вы должны объявить свой указатель на функцию C++, используя __stdcall Соглашение о вызовах. (Спасибо, Александр С!)

  2. В функции обратного вызова VB явно пометьте ваши параметры как побочные, используя ключевое слово ByVal, Точно так же, в вашем указателе функции C++ не помечайте ваши параметры как ссылки.

  3. Если вы хотите передать строку в обратный вызов или извлечь строку из нее, вы должны принять во внимание, что VB Strings не равны C char*с, С ++ std::stringс или Microsoft CStrings. VB Strings должны быть сопоставлены с довольно неясным Microsoft BSTR тип данных.

  4. Я забыл очень важную вещь: ваш обратный вызов должен быть внутри модуля VB (т. Е. Он должен быть "простой функцией", а не классом или методом формы).

Ваш начальник может вызывать функции, экспортируемые из DLL, с помощью оператора Declare. Это не очень хорошо масштабируется, но хорошо для простого API. Ваша функция должна быть экспортирована с помощью объявлений extern "C" и __declspec(dllexport), использовать соглашение о вызовах __stdcall и использовать только простые типы аргументов.

Возьмите Unix-Y маршрут. Создайте ПРОГРАММУ, которая выполняет копирование и выводит индикатор выполнения на стандартный вывод. Заставьте приложение VB анализировать этот вывод, чтобы получить процент выполнения.

Когда он должен предоставлять эти обновления статуса?
При настройке VSS? Или во время резервного копирования данных и тому подобное? В последнем случае VSS просто возвращает путь, который можно использовать непосредственно из VB.
Но для настройки... это тоже может иметь смысл, потому что это может быть довольно медленно, но я думаю, вы можете превратить его в конечный автомат - поместите все вызовы VSS API в большой switch() и сделайте функцию, которая будет вызывать их по одному и обновите состояние вар.

Обновление: я имею в виду что-то вроде этого. Init() и Step() - ваши функции, экспортируемые вашей DLL и вызываемые из VB.
В качестве альтернативы, вы можете создать поток, чтобы сделать все это (все еще в dll) и возвращать обновления статуса после, как Sleep(100) в Step().

int s; // state

int Init( void ) { s=0; }

int Step( void ) {

  switch( s ) {

    default: break;

    case 0: 
    CoInitialize(0); break;

    case 1: 
    r = CreateVssBackupComponents(&vssc); 
    if( FAILED(r) ) s=-1;
    if( vssc==0 ) s=-2;
    break;

    case 2: 
    r = vssc->InitializeForBackup();
    if( FAILED(r) ) s=-3; 
    break;

    case 3: 
    r = vssc->SetBackupState( FALSE, FALSE, VSS_BT_COPY, FALSE );
    if( FAILED(r) ) s=-4;
    break;

    [...]

  }

  s += (s>=0);
}

Я бы сделал это:

  • приложение VB вызывает функцию в вашей DLL с просьбой запустить теневую копию. Ваш Dll запускает поток, который выполняет теневое копирование и возвращает идентификатор (идентификатор потока?) Обратно в приложение VB

  • Приложение VB периодически вызывает функцию "Прогресс" в вашей DLL, передавая идентификатор операции, полученный ранее: функция прогресса возвращает целое число 0-100, чтобы указать прогресс

  • Таким образом, приложение VB может запускать несколько операций параллельно.

Поток, который выполняет копирование, должен время от времени обновлять переменную "progress". Другая функция в DLL, которая останавливает копирование, также будет полезна.

Я бы сделал эту работу без COM. Вместо этого я хотел бы, чтобы часть VB отправляла дескриптор окна в DLL, и DLL будет публиковать в окне сообщение о своем прогрессе.

Вы могли бы использовать COM, но это похоже на удар мухи кувалдой.

Другие вопросы по тегам