C++ DLL,可以通知调用程序其进度

发布于 2024-10-22 20:21:20 字数 453 浏览 2 评论 0原文

我的老板希望我用 C++ (MSVC++2010) 编写一个 DLL,它可以执行卷影复制,他可以从 VB6(或稍后其他语言)调用它,并且可以在未完成时返回状态更新。他称之为“事件”。

我有一种感觉,我终于需要学习COM了(我宁愿不...)...而且,我想到了一个回调函数,但是函数指针从VB6移交给C++肯定是不可能的?

有人可以概述一下我必须学习什么以及如何在使用或不使用 COM 的情况下实现这一点吗?

编辑: 回答一个问题,工作流程应该是:

  1. VB6 应用程序确定要备份哪些文件

  2. 我得到一个路径并创建一个临时卷影子复制其中包含此路径并返回安装点(或类似的)

    • 在此步骤中,我会定期告诉 VB6 应用程序我还有多远

  3. VB6 应用程序备份卷影副本,然后删除卷影副本。

My boss wants me to write a DLL in C++ (MSVC++2010) which can perform a Volume Shadow Copy which he can call from VB6 (or at a later point other languages) and which can give status updates back while it is not finished. He calls it "events".

I have the feeling that I finally need to learn COM (I'd rather not ...) ... also, a callback function comes to my mind, but it's surely impossible to hand over function pointers from VB6 to C++?

Can someone outline what I have to learn and how this can be accomplished, with or without COM?

EDIT:
to answer a question, the work flow is supposed to be:

  1. VB6 app determines which files to back up

  2. I am given a path and make a temporary volume shadow copy which includes this path and give back a mount point (or similar)

    • during this step, I regularly tell the VB6 app how far I am
  3. VB6 app makes backup of shadow copy and then deletes shadow copy.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

冰之心 2024-10-29 20:21:20

您可以使用 AddressOf 运算符将指向“显示进度”函数的指针从 VB 应用程序传递到 C++ DLL 应用程序:

Declare Function CallMyDll ...

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

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

一些不太明显的陷阱:

  1. 您必须声明 C++ 函数指针使用 __stdcall 调用约定。 (谢谢,Alexandre C!)

  2. 在您的 VB 回调函数中,将您的参数显式标记为按值< /a> 使用关键字 ByVal。同样,在 C++ 函数指针中,不要将参数标记为引用。

  3. 如果您想将字符串传递给回调,或从中检索字符串,则必须考虑到 VB String 不等于 C char*、C++ std::string 或 Microsoft 的 CString。 VB String 必须映射到 Microsoft 相当晦涩的 BSTR 数据类型。

  4. 我忘记了一件非常重要的事情:您的回调必须位于 VB 模块内(即,它必须是“纯粹的函数”,而不是类或表单的方法)。< /p>

You can pass a pointer to your "display progress" function from the VB app to the C++ DLL app using the AddressOf operator:

Declare Function CallMyDll ...

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

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

Some not so obvious gotchas:

  1. You have to declare your C++ function pointer using the __stdcall calling convention. (Thanks, Alexandre C!)

  2. In your VB callback function, explicitly mark your parameters as by-value using the keyword ByVal. Similarly, in your C++ function pointer, don't mark your parameters as by-reference.

  3. If you want to pass a string to the callback, or retrieve a string from it, you have to take into consideration that VB Strings are not equal to C char*s, C++ std::strings, or Microsoft's CStrings. VB Strings must be mapped to Microsoft's rather obscure BSTR data type.

  4. I forgot a very important thing: Your callback has to be inside a VB Module (i.e., it has to be a "mere function", not a class' or a form's method).

丶视觉 2024-10-29 20:21:20

您的老板可以使用 Declare 语句调用 DLL 导出的函数。这不能很好地扩展,但对于简单的 API 来说已经足够了。您的函数应使用 extern "C" 和 __declspec(dllexport) 声明符导出,使用 __stdcall 调用约定并仅使用简单的参数类型。

Your boss can call functions exported by a DLL with the Declare statement. That doesn't scale well but is fine for a simple API. Your function should be exported with the extern "C" and __declspec(dllexport) declarators, use the __stdcall calling convention and use only simple argument types.

倾城花音 2024-10-29 20:21:20

什么时候必须提供这些状态更新?
设置 VSS 时?或者在备份数据之类的时候?
在后一种情况下,VSS仅返回一个路径,可以使用该路径
直接来自 VB。
但对于设置......这也可能有意义,因为它可能相当慢,
但我想你可以把它变成一个状态机 - 把所有的 VSS API 调用
进入一个大的 switch() 并创建一个函数来一一调用它们
更新状态变量。

更新:我的意思是这样的。
Init() 和 Step() 是由 dll 导出并从 VB 调用的函数。
或者,您可以生成一个线程来完成所有这些操作(仍在 dll 中)并返回
像 Step() 中的 Sleep(100) 一样,状态会更新。

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);
}

When it has to provide these status updates?
While setting up VSS? Or while backing up the data and such?
In the latter case VSS just returns a path, which can be used
directly from VB.
But for setup... it might make sense too, because it can be fairly slow,
but I guess you can turn it into a state machine - put all the VSS API calls
into a big switch() and make a function which would call them one by one and
update the state var.

Update: I mean something like this.
Init() and Step() are your functions exported by your dll and called from VB.
Alternatively, you can spawn a thread to do all that (still in the dll) and return
status updates after like Sleep(100) in 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);
}
我是男神闪亮亮 2024-10-29 20:21:20

我会在没有 COM 的情况下完成这项工作。相反,我会让 VB 部分向 DLL 发送一个窗口句柄,然后 DLL 将向窗口发布一条消息,告知其进度。

您可以使用 COM,但这有点像用大锤打苍蝇。

I would do the job without COM. Instead, I'd have the VB part send a window handle to the DLL, and the DLL will post a message to the window telling its progress.

You could use COM, but that's kind of in the range of swatting a fly with a sledgehammer.

昨迟人 2024-10-29 20:21:20

走unix-y路线。创建一个执行复制并将进度指示器输出到标准输出的程序。让 VB 应用程序解析此输出以获取完成百分比。

Take the unix-y route. Create a PROGRAM that performs the copy and outputs a progress indicator to std out. Make the VB app parse this output to grab the completion percentage.

哭了丶谁疼 2024-10-29 20:21:20

我会这样做:

  • VB 应用程序调用 DLL 中的函数,要求启动卷影副本。您的 Dll 启动一个执行卷影复制的线程,并将 ID(线程 ID?)返回给 VB 应用程序

  • VB 应用程序定期调用 DLL 中的函数“Progress”,传递之前收到的操作 ID:进度函数返回一个 0-100 的整数来指示进度

  • 这样VB 应用程序可以并行启动多个操作。

执行复制的线程应该时不时地更新“进度”变量。
DLL 中另一个停止复制的函数也很有用。

I would do this:

  • the VB app calls the function in your DLL asking to start the shadow copy. Your Dll starts a thread that performs the shadow copy and returns an ID (a thread id?) back to the VB app

  • The VB app calls periodically a function "Progress" in your DLL passing the operation ID received before: the progress function returns an integer 0-100 to indicate the progress

  • This way the VB app can launch several operations in parallel.

The thread that performs the copy should update a "progress" variable every now and then.
Another function in the DLL that stops the copy would be useful too.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文