C ++ DLL, которая может информировать вызывающую программу о ее прогрессе - PullRequest
2 голосов
/ 17 марта 2011

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

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

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

РЕДАКТИРОВАТЬ: ответить на вопрос,рабочий процесс должен выглядеть следующим образом:

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

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

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

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

Ответы [ 6 ]

5 голосов
/ 17 марта 2011

Вы можете передать указатель на функцию «Отображение прогресса» из приложения 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 соглашение о вызовах .(Спасибо, Александр C!)

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

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

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

2 голосов
/ 17 марта 2011

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

1 голос
/ 18 марта 2011

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

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

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

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

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

1 голос
/ 17 марта 2011

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

1 голос
/ 17 марта 2011

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

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

1 голос
/ 17 марта 2011

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

Обновление: я имею в виду нечто подобное.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);
}
...