在多个 DLL 实例中使用 wxWidgets (wxMSW) 时出现问题

发布于 2024-07-26 20:23:32 字数 2220 浏览 4 评论 0原文

前言

我正在开发 VST 插件,它们是基于 DLL 的软件模块,由支持 VST 的主机应用程序加载。 要打开 VST 插件,主机应用程序会加载 VST-DLL 并调用插件的适当函数,同时提供本机窗口句柄,插件可以使用该句柄来绘制其 GUI。 我成功移植了我原来的 VSTGUI 代码到wxWidgets-Framework,现在我所有的插件都在wxMSW和wxMac下运行,但我在wxMSW下仍然遇到问题,无法找到打开和关闭插件的正确方法,我不确定这是否是wxMSW独有的问题。

问题

如果我使用任何 VST 主机应用程序,我可以毫无问题地打开和关闭我的 VST 插件之一的多个实例。 一旦我打开第一个 VST 插件之外的另一个 VST 插件,然后关闭第一个 VST 插件的所有实例,应用程序就会在 wxEventHandlerr::ProcessEvent 函数内的一小段时间后崩溃,告诉我 wxTheApp 对象在 wxTheApp->FilterEvent 执行期间不再有效(见下文)。 因此,似乎 wxTheApp 对象在关闭第一个插件的所有实例后被删除,并且不再可用于第二个插件。

bool wxEvtHandler::ProcessEvent(wxEvent& event)
{
    // allow the application to hook into event processing
    if ( wxTheApp )
    {
        int rc = wxTheApp->FilterEvent(event);
        if ( rc != -1 )
        {
            wxASSERT_MSG( rc == 1 || rc == 0,
                          _T("unexpected wxApp::FilterEvent return value") );

            return rc != 0;
        }
        //else: proceed normally
    }

    ....
}

先决条件

1.) 我的所有 VST 插件都动态链接到 C-Runtime 和 wxWidgets 库。 关于wxWidgets 论坛这似乎是并行运行该软件的多个实例的最佳方式。

2.) 每个 VST-Plugin 的 DllMain 定义如下:

// WXW
#include "wx/app.h"
#include "wx/defs.h"
#include "wx/gdicmn.h"
#include "wx/image.h"

#ifdef __WXMSW__
#include <windows.h>
#include "wx/msw/winundef.h"

BOOL APIENTRY DllMain
( HANDLE hModule,
  DWORD ul_reason_for_call,
  LPVOID lpReserved )
{
        switch (ul_reason_for_call)
        {
            case DLL_PROCESS_ATTACH:
        {
                  wxInitialize();
                ::wxInitAllImageHandlers();
            break;
        }
            case DLL_THREAD_ATTACH:
                       break;
            case DLL_THREAD_DETACH:
                       break;
            case DLL_PROCESS_DETACH:
                       wxUninitialize();
                           break;
        }

    return TRUE; 
}

#endif // __WXMSW__

class Application : public wxApp {};
IMPLEMENT_APP_NO_MAIN(Application)

问题

我怎样才能分别防止这种行为 如果我有多个实例,我怎样才能正确处理 wxTheApp 对象 不同的 VST 插件(DLL 模块),它们动态链接到 C 运行时和 wxWidgets 库?

最好的问候,史蒂芬

Preface

I'm developing VST-plugins which are DLL-based software modules and loaded by VST-supporting host applications. To open a VST-plugin the host applications loads the VST-DLL and calls an appropriate function of the plugin while providing a native window handle, which the plugin can use to draw it's GUI. I managed to port my original VSTGUI
code to the wxWidgets-Framework and now all my plugins run under wxMSW and wxMac but I still have problems under wxMSW to find a correct way to open and close the plugins and I am not sure if this is a wxMSW-only issue.

Problem

If I use any VST-host application I can open and close multiple instances of one of my VST-plugins without any problems. As soon as I open another of my VST-plugins besides my first VST-plugin and then close all instances of my first VST-plugin the application crashes after a short amount of time within the wxEventHandlerr::ProcessEvent function telling me that the wxTheApp object isn't valid any longer during execution of wxTheApp->FilterEvent (see below). So it seems to be that the wxTheApp objects was deleted after closing all instances of the first plugin and is no longer available for the second plugin.

bool wxEvtHandler::ProcessEvent(wxEvent& event)
{
    // allow the application to hook into event processing
    if ( wxTheApp )
    {
        int rc = wxTheApp->FilterEvent(event);
        if ( rc != -1 )
        {
            wxASSERT_MSG( rc == 1 || rc == 0,
                          _T("unexpected wxApp::FilterEvent return value") );

            return rc != 0;
        }
        //else: proceed normally
    }

    ....
}

Preconditions

1.) All my VST-plugins a dynamically linked against the C-Runtime and wxWidgets libraries. With regard to the wxWidgets
forum this seemed to be the best way to run multiple instances of the software side by side.

2.) The DllMain of each VST-Plugin is defined as follows:

// WXW
#include "wx/app.h"
#include "wx/defs.h"
#include "wx/gdicmn.h"
#include "wx/image.h"

#ifdef __WXMSW__
#include <windows.h>
#include "wx/msw/winundef.h"

BOOL APIENTRY DllMain
( HANDLE hModule,
  DWORD ul_reason_for_call,
  LPVOID lpReserved )
{
        switch (ul_reason_for_call)
        {
            case DLL_PROCESS_ATTACH:
        {
                  wxInitialize();
                ::wxInitAllImageHandlers();
            break;
        }
            case DLL_THREAD_ATTACH:
                       break;
            case DLL_THREAD_DETACH:
                       break;
            case DLL_PROCESS_DETACH:
                       wxUninitialize();
                           break;
        }

    return TRUE; 
}

#endif // __WXMSW__

class Application : public wxApp {};
IMPLEMENT_APP_NO_MAIN(Application)

Question

How can I prevent this behavior respectively how can I properly handle the wxTheApp object if I have multiple instances
of different VST-plugins (DLL-modules), which are dynamically linked against the C-Runtime and wxWidgets libraries?

Best reagards, Steffen

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

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

发布评论

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

评论(2

人海汹涌 2024-08-02 20:23:32

当 wxWidgets 应用程序加载我们的 DLL 时,我们在使用通过 wxWidgets 创建的 LSP 时遇到了类似的问题。 在调用::wxInitialize()之前检查NULL == wxTheApp。

伪代码:

BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
    switch(dwReason) {
        case DLL_PROCESS_ATTACH :
            if(NULL == wxTheApp) {
                ::wxInitialize();
            }
            break;
    }
}

另外,我建议在 DllMain() 中尽可能少做一些事情,例如,如果可能的话,将 wxInitAllImageHandlers() 移到其他地方。 此外,您可能希望跟踪是否调用了 ::wxInitialize() 来与 ::wxUninitialize() 配对

We had similar issues using a LSP created with wxWidgets when an wxWidgets application loaded our DLL. Check for NULL == wxTheApp before calling ::wxInitialize().

Pseudo code:

BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
    switch(dwReason) {
        case DLL_PROCESS_ATTACH :
            if(NULL == wxTheApp) {
                ::wxInitialize();
            }
            break;
    }
}

Also, I suggest doing as little possible in your DllMain() as possible, e.g. move wxInitAllImageHandlers() elsewhere if possible. Additionally, you may wish to track if you called ::wxInitialize() to pair up with ::wxUninitialize()

人海汹涌 2024-08-02 20:23:32

我遇到了类似的问题,但使用的是 Acrobat 插件。
在将 Acrobat 插件调整为 Acrobat X (10) 时,我们必须删除与 ADM 相关的代码(Acrobat 对话框管理器 - 曾经是 Acrobat 7、8 和 9 上的跨平台 GUI 框架。已随 Acrobat X 删除)并使用不同的GUI框架。

Acrobat SDK 附带了使用 wxWidgets 作为跨平台框架的示例,因此我们就朝这个方向发展(我们支持 MAC 和 Windows)。
Acrobat 的插件架构与您上面描述的非常相似:dll(对于 Acrobat 插件,二进制文件扩展名为 *.api),它们由主进程(exe)动态加载,并且它们的函数在文档中调用,预定义的顺序。

因为 Acrobat wxWidgets 示例是使用 2.8.12 编写的,并且由于这是稳定版本,所以我们决定不使用 2.9.x 持续版本。

因此,我们将插件(总共 3 个不同的插件)静态链接到 wx2.8.12 库,并发现如果安装了其中 3 个,则最后加载的两个将无法运行。 我的意思是 - 我们自定义的 wxFrames、wxWindows 和 wxFrames。 属于这两个插件的 wxDialogs 都被搞乱了(就像有人试图用橡皮擦掉它们一样:-))。

通过深入挖掘,我们将范围缩小到这样一个事实:第一个插件被加载,初始化 wxWidgets,而后者则没有,即使显式调用了 wxInitialize()。 出了点问题......

这里我忘了提及 - 在 Acrobat 插件中,您无法更改 DllMain() 函数,因此 wx 的初始化是在“插件 Init() 函数”中完成的。

需要明确的是 - wx 库静态链接到 *.api 文件,因此每个库都应该有自己的“副本”,并且不会相互影响。

使用 Google 2-3 整天,我设法找到 此帖子
,建议应用补丁(仅适用于2.8x!!!)。 我相信(或希望)2.9.x 版本不会遇到这个问题(没有机会检查它)。

顺便说一句 - 该补丁只是一个非常清晰的文件,因此阅读代码以理解它并保持冷静,它不会造成任何损害,这是非常容易的。

我希望其他使用 wx 2.8.x 并遇到同样问题的人会发现这一点。

奥姆里

I encountered a similar issue but with Acrobat plugins.
While adjusting our Acrobat plugins to Acrobat X (10) we had to remove code related to ADM (Acrobat Dialog Manager - Used to be a cross-platform GUI framework on Acrobat 7, 8 & 9. Removed with Acrobat X) and use a different GUI framework.

Acrobat SDK comes with samples of using wxWidgets as a cross-platform framework so we headed that way (we support MAC & Windows).
The plugin architecture of Acrobat is very similar to the one you described above: dlls (for Acrobat plugins the binary file extension is *.api) which are dynamically loaded by a main process (exe) and their functions are being called in a documented, pre-defined order.

Because the Acrobat wxWidgets example was written with 2.8.12 and due to the fact that this is the stable version we decided to NOT use the 2.9.x ongoing version.

So we statically linked our plugins (total of 3 different plugins) to the wx2.8.12 libs and found out that if 3 of them are installed, the two that were loaded last were not functioning. By that I mean - Our custom wxFrames, wxWindows & wxDialogs belonging to these two plugins were all messed up (like someone tried to erase them, with rubber :-)).

Digging deeply we narrowed it down to the fact that the first plugin being loaded, initializes wxWidgets and the latter do not, even though the explicit call to wxInitialize(). Something there went wrong....

Here I forgot to mention - In an Acrobat plugin you cannot change the DllMain() function, so the initialization of wx is done in a "Plugin Init() function".

Just to be clear - The wx libs are statically linked to the *.api files, so each should have a "copy" of its own and not influence on each other.

Using Google for 2-3 FULL days I managed to find this post
,which suggested to apply this patch (for 2.8x ONLY!!!). I believe (or hope) that the 2.9.x version does not suffer from this issue (didn't have the chance to check it).

BTW - The patch is only one file which is very clear, so reading the code to understand it and to be calm that it does no harm is pretty easy.

I hope others using wx 2.8.x and suffering from the same issue will find this.

Omri

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