Проблемы с созданием GUI из DLL

Это русская секция форума wxWidjets. В этой секции вы можете обсуждать любые вопросы, связанные с wxWidgets на вашем родном языке.
Post Reply
VantuZZ
In need of some credit
In need of some credit
Posts: 6
Joined: Fri May 07, 2010 9:33 am
Location: russia
Contact:

Проблемы с созданием GUI из DLL

Post by VantuZZ » Fri May 07, 2010 10:26 am

Приветствую всех виджетистов!
Помогите пожалуйста реализовать следующую идею:
Я загружаю динамическую DLL и получаю оттуда класс(интерфейс плагина), в свою очередь интефейс получает ссылку на основное окно и необходимые методы. Я пытаюсь создать в DLL пустое wxWindow , добавляю туда sizer с необходимым мне интерфейсом и отдаю его aui_manager'у(основного окна) хочу чтобы он присоединил окно созданное в DLL. Если я это делаю в лоб(без запуска run_wx_gui_from_dll() из примера с DLL с wx SVN'а )то все крошится на месте, если я использую эту функцию для создания потока для обработки GUI то все создается но стоит кликнуть по созданному окну и все крошится, если я создаю пустое окно в основном классе фрейма(который запускается в exe), то все хороше, и далее я создаю уже компоненты прям в DLL но события от них не доходят до окна в котором они отрисовываются, я кончено пробовал создовать скажем пустую кнопку в основном окне и использовать уже ее, но это не дело для каждого GUI элемента обращатся к окну, все таки правильно их создавать прям в DLL, но тогда опять же лажа с событиями, кто сталкивался с подобным, и кто либо может объяснить мне разницу в написании строк

Code: Select all

new wxButton(parent, ...);
в класе основного окна и в DLL функции которую вызывает основное окно, никак не могу разобраться, заранее спасибо!

Хочу добавить что создавать frame'ы и dialog'и из DLL выходит без проблем.
wxWidgets 2.9.1, Visual Studio 2008, win XP

VantuZZ
In need of some credit
In need of some credit
Posts: 6
Joined: Fri May 07, 2010 9:33 am
Location: russia
Contact:

Post by VantuZZ » Fri May 07, 2010 9:13 pm

Нашел решение своей проблемы, правда собрать не получилось, м.б. кто то уже сталкивался с этим исходником - http://wiki.wxwidgets.org/Programs_That_Support_Plugins ?

Выдает след. ошибку при нажатии кнопки "Do it":
Необработанное исключение в "0x010b6dd3 (samplePlugin.dll)" в "DLL_test.exe": 0xC0000005: Нарушение прав доступа при чтении "0x00000000".
и указывает на 435 строку msgdlg.cpp

Code: Select all

int wxMessageDialog::ShowModal()
{
    if ( !wxTheApp->GetTopWindow() )
    {
...
Вообще буду очень признателен если у кого нибудь есть пример связки exe + dll где из DLL создается и обрабатывается окно внутри основного окна exe, вообщем как по ссылке выше только для MVS.
wxWidgets 2.9.1, Visual Studio 2008, win XP

SandyHip
Earned a small fee
Earned a small fee
Posts: 11
Joined: Wed Jun 02, 2010 9:44 am

Re: Проблемы с созданием GUI из DLL

Post by SandyHip » Fri Jul 01, 2011 11:00 am

У меня проблема несколько иного характера
WinXP, wxWidgets 2.8.3 static link UNICODE, Compiller - MinGW GCC 3.4.5

В своей DLL я реализовал фрейм, у которого определены свои обработчики событий.
При загрузке DLL выполняется функция:

Code: Select all

class wxDLLApp : public wxApp { // без этого класса не работает
public:
    bool OnInit() {return true;}
};
DECLARE_APP(wxDLLApp)
IMPLEMENT_APP_NO_MAIN(wxDLLApp)

wxMyFrame* g_pFrame = NULL;

__attribute__((constructor)) void init()
{
    ::wxInitialize();
    g_pFrame = new wxMyFrame(NULL, wxID_ANY); // наследник wxFrame
}
При отключении DLL выполняется функция:

Code: Select all

__attribute__((destructor)) void fini()
{
    if (g_pFrame != NULL) g_pFrame->Destroy();
    ::wxUninitialize();
}
И также есть функции extern "C", вызывающие некоторые public-методы wxMyFrame

При загрузке этой DLL из MFC приложения (без использования wxWidgets) - все работает нормально.
При загрузке этой DLL из wxWidgets приложения - события не отрабатывают, хотя методы класса вызываются.

Я тоже думал на счет плагина, но много переписывать. Дело в том, что этот же фрейм я использую еще и в exe.

borr_1
Super wx Problem Solver
Super wx Problem Solver
Posts: 362
Joined: Wed Mar 07, 2007 8:10 am
Location: Russia, Shakhty

Re: Проблемы с созданием GUI из DLL

Post by borr_1 » Fri Jul 01, 2011 12:24 pm

Читал? http://wiki.wxwidgets.org/Creating_A_DL ... pplication на беглый взгляд у тебя чего-то не хватает
WinXP SP3, wx-2.8.10, MinGW-4.4.1, gdb-7.1.2, eclipse

SandyHip
Earned a small fee
Earned a small fee
Posts: 11
Joined: Wed Jun 02, 2010 9:44 am

Re: Проблемы с созданием GUI из DLL

Post by SandyHip » Fri Jul 01, 2011 1:05 pm

Читал.
Напомню: wxWidgets 2.8.3 Compiller - MinGW GCC 3.4.5
Не думаю, что в DLL на GCC будет выполняться DllMain...

borr_1
Super wx Problem Solver
Super wx Problem Solver
Posts: 362
Joined: Wed Mar 07, 2007 8:10 am
Location: Russia, Shakhty

Re: Проблемы с созданием GUI из DLL

Post by borr_1 » Fri Jul 01, 2011 1:53 pm

wxApp::SetInstance где? Я смотрю там в примерах немного другой код - ясное дело помимо DllMain там перед ним дефине вхмсв стоит.
WinXP SP3, wx-2.8.10, MinGW-4.4.1, gdb-7.1.2, eclipse

SandyHip
Earned a small fee
Earned a small fee
Posts: 11
Joined: Wed Jun 02, 2010 9:44 am

Re: Проблемы с созданием GUI из DLL

Post by SandyHip » Mon Jul 04, 2011 6:10 am

wxApp::SetInstance(new wxDLLApp());
Пробовал.
Из программы не на wx - работает
Из программы на wx - не работает
Без SetInstance - картина та же

borr_1
Super wx Problem Solver
Super wx Problem Solver
Posts: 362
Joined: Wed Mar 07, 2007 8:10 am
Location: Russia, Shakhty

Re: Проблемы с созданием GUI из DLL

Post by borr_1 » Mon Jul 04, 2011 6:33 am

Я просто смотрю у них

Code: Select all

Header file : wxWidgetsDLL.h


 #ifndef wxWidgetsDLLH
 #define wxWidgetsDLLH
 
 #pragma once
 
 /*This is the method i use to link the libs to my DLL project in c++ builder 6, not used with eg. mingw32/dev-cpp
   if anybody has a hint on c++ builder 6 linking, just tell me 
 */
 #ifdef CBUILDER
 #pragma link "wxzlib.lib" 
 #pragma link "wxmsw26.lib"
 #endif
 
 #include "wx/wx.h"
 
 #include <windows.h>
 #include <process.h>
 
 HANDLE ThreadId;
 
 class wxDLLApp : public wxApp
 {
 	bool OnInit();
 };
 
 #endif wxWidgetsDLLH 
 


Source file : wxWidgetsDLL.cpp

 #include "wx/wx.h"
 #include <process.h> 
 #include "Unit1.h" 
 
 IMPLEMENT_APP_NO_MAIN(wxDLLApp)
 
 DWORD WINAPI ThreadProc(LPVOID lpParameter)
 {
     wxApp::SetInstance(new wxDLLApp());
     wxEntry(GetModuleHandle(NULL),NULL,NULL,SW_SHOW);
     return true;
 }

У тебя немного не так да ты еще и ::wxInitialize(); в инит вставил. Я сам над этим вопросом не экспериментировал, но где-то здесь, в русской, ветке такой вопрос человек уже задавал (по-моему).
WinXP SP3, wx-2.8.10, MinGW-4.4.1, gdb-7.1.2, eclipse

SandyHip
Earned a small fee
Earned a small fee
Posts: 11
Joined: Wed Jun 02, 2010 9:44 am

Re: Проблемы с созданием GUI из DLL

Post by SandyHip » Mon Jul 04, 2011 8:27 am

Перед тем как сюда написать я пробовал указанный тобой пример
Т.к. DllMain в библиотеке на GCC не выполняется я заменил ее на
__attribute__((constructor)) void init(); - функция выполняемая при загрузке
__attribute__((destructor)) void fini(); - функция выполняемая при выгрузке
Была еще и такая попытка:

Code: Select all

__attribute__((constructor)) void init()
{
    wxApp::SetInstance(new wxDLLApp());
    //::wxEntry(GetModuleHandle(NULL),NULL,NULL,SW_SHOW); // Приводит к зависанию
    ::wxEntryStart(wxTheApp->argc, wxTheApp->argv);
    /* ... */
}

__attribute__((destructor)) void fini()
{
    /* ... */
    ::wxEntryCleanup();
}
Поведение абсолютно аналогично первому примеру (::wxInitialize(); в init ::wxUninitialize(); в fini):
1. Собираю приложение на MFC в MSVC - все отрабатывает, фрейм появляется, события обрабатываются
2. Собираю приложение на wx (static link) в Code::Blocks (GCC) - фрейм появляется, события не обрабатываются
Напомню, DLL собрана на GCC со статической линковкой баблиотек

borr_1
Super wx Problem Solver
Super wx Problem Solver
Posts: 362
Joined: Wed Mar 07, 2007 8:10 am
Location: Russia, Shakhty

Re: Проблемы с созданием GUI из DLL

Post by borr_1 » Mon Jul 04, 2011 8:53 am

где там DllMain в том коде что я сюда запостил хоть стреляй не пойму.
WinXP SP3, wx-2.8.10, MinGW-4.4.1, gdb-7.1.2, eclipse

SandyHip
Earned a small fee
Earned a small fee
Posts: 11
Joined: Wed Jun 02, 2010 9:44 am

Re: Проблемы с созданием GUI из DLL

Post by SandyHip » Mon Jul 04, 2011 9:31 am

Я имел в виду этот пример:
http://wiki.wxwidgets.org/Creating_A_DL ... UI_support

borr_1
Super wx Problem Solver
Super wx Problem Solver
Posts: 362
Joined: Wed Mar 07, 2007 8:10 am
Location: Russia, Shakhty

Re: Проблемы с созданием GUI из DLL

Post by borr_1 » Mon Jul 04, 2011 9:52 am

В этом примере я опять не вижу DllMain

http://forums.wxwidgets.org/viewtopic.p ... =extern+C+

ну и в конце концов если тебе так нужна DllMain
http://forum.vingrad.ru/forum/topic-280 ... mingw.html
WinXP SP3, wx-2.8.10, MinGW-4.4.1, gdb-7.1.2, eclipse

SandyHip
Earned a small fee
Earned a small fee
Posts: 11
Joined: Wed Jun 02, 2010 9:44 am

Re: Проблемы с созданием GUI из DLL

Post by SandyHip » Tue Jul 05, 2011 12:29 pm

В общем получилось
Проблема вызова DllMain заключалась в том, что объявить ее надо было так:

Code: Select all

extern "C" BOOL __stdcall DllMain(HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
А от функций __attribute__((constructor)) void init() и __attribute__((destructor)) void fini() пришлось отказаться.
Несмотря на то, что компилятор - GCC, ОС, по прежнему, Windows
Пример таков:
mydll.h

Code: Select all

class wxDLLApp : public wxApp {
public:
    wxDLLApp()
    {
        SetExitOnFrameDelete(false);
    }
public:
    bool OnInit() {return true;}
    int OnExit() {return wxApp::OnExit();}
};
DECLARE_APP(wxDLLApp)
mydll.cpp

Code: Select all

#include "mydll.h"

/* ...*/ 

#ifdef __WXMSW__ // Макрос __WXMSW__ касается не компилятора
#include <wx/dynlib.h>

HANDLE g_DllThread = NULL;

HMODULE MSWGetModuleHandle(const char *name, void *addr)
/*Эту функцию я честно передрал из static WXHMODULE wxDynamicLibrary::MSWGetModuleHandle(const char *name, void *addr); wxWidgets 2.9.2*/
{
    typedef BOOL (WINAPI *GetModuleHandleEx_t)(DWORD, LPCSTR, HMODULE *);
    static const GetModuleHandleEx_t INVALID_FUNC_PTR = (GetModuleHandleEx_t)-1;
    static GetModuleHandleEx_t s_pfnGetModuleHandleEx = INVALID_FUNC_PTR;

    if (s_pfnGetModuleHandleEx == INVALID_FUNC_PTR) {
        wxDynamicLibrary dll(wxT("kernel32.dll"), wxDL_VERBATIM);
        s_pfnGetModuleHandleEx = (GetModuleHandleEx_t)dll.RawGetSymbol(wxT("GetModuleHandleExA"));
    }
    if (s_pfnGetModuleHandleEx) {
        HMODULE hModule;
        if (s_pfnGetModuleHandleEx(6, (char*)addr, &hModule) && hModule) return hModule;
    }
    return ::GetModuleHandleA((char*)name);
}

DWORD __stdcall ThreadProc(LPVOID lpParameter)
{
    wxApp::SetInstance(new wxDLLApp());
    ::wxEntry(MSWGetModuleHandle("mydll", &g_DllThread), NULL, NULL, SW_SHOW);
    /*"mydll" - имя DLL*/
    return 1;
}

extern "C" BOOL __stdcall DllMain(HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call) {
        case DLL_PROCESS_ATTACH:
            ::wxInitialize();
            g_DllThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
            g_pFrame = new wxMyFrame(NULL, wxID_ANY);
            break;
        case DLL_THREAD_ATTACH: break;
        case DLL_THREAD_DETACH: break;
        case DLL_PROCESS_DETACH:
            if (g_pFrame != NULL) {
                g_pFrame->Destroy();
            }
            ::wxEntryCleanup();
            ::wxUninitialize();
            break;
     }
     return TRUE;
}
#endif
Другие функции библиотеки, объявленные как extern "C" int __declspec(dllexport), вызывают public-методы wxMyFrame, в том числе и wxMyFrame::Show(bool)

borr_1, спасибо за полезные ссылки

Post Reply