CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - DLL i Form1 cz.2

DLL i Form1 cz.2

problemy z funkcjonowaniem bibliotek, komponentów itp.

DLL i Form1 cz.2

Nowy postprzez bodjanski » sobota, 4 grudnia 2010, 16:06

Witam

Wiemy, że do biblioteki dll można dołączać obiekty VCL np. zwykłą formę czy jak kto woli formularz. Problem pojawił się, gdy chciałem użyć takiej biblioteki wykorzystując bibliotekę importową *.lib (nie dynamicznie, za pomocą funkcji LoadLibrary). W zalezności od stopnia skomplikowania głównej aplikacji, można zaobserwować różne dziwne rzeczy np:

1) okno z biblioteki dll manifestuje się jako osobna aplikacja na pasku zadań

Sprawy komplikują się gdy zaczynam manipulować opcjami 'Linkier \ Use dynamic RTL' oraz 'Packages \ Build with runtime packages' lub dodaję komponent TXPManifest. Generalnie zaobserwowałem jeszcze takie czary:

2) okno aplikacji nie chce się minimalizować lub nie 'przebija' się przez inne okna
3) inne okna aplikacji też pojawiają się na pasku zadań jako osobne etykiety
4) przy zamykaniu aplikacji powstaje błąd "access violations"

W załączniku są dwa projekty (aplikacji - 'robo.bdsproj' i biblioteki - 'okno.bdsproj') napisane w BDS2006. Poniżej najwazniejsze fragmenty kodów źródłowych:

plik okno.h
Kod: Zaznacz cały
//---------------------------------------------------------------------------
#ifndef OknoH
#define OknoH

#ifdef BUILD_DLL
  #define DLL_MODE __declspec(dllexport)
#else
  #define DLL_MODE __declspec(dllimport)
#endif

extern "C" DLL_MODE void __stdcall Okno_Create();
extern "C" DLL_MODE void __stdcall Okno_Destroy();
extern "C" DLL_MODE void __stdcall Okno_Show();

#endif
//---------------------------------------------------------------------------


plik oknoUnit1.cpp
Kod: Zaznacz cały
//---------------------------------------------------------------------------

#include <vcl.h>
#include <windows.h>
#pragma hdrstop

#include "oknoUnit2.h"
#define BUILD_DLL
#include "okno.h"
//---------------------------------------------------------------------------
//   Important note about DLL memory management ...
//---------------------------------------------------------------------------

#pragma argsused
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)
{
   return 1;
}
//---------------------------------------------------------------------------
void __stdcall Okno_Create()
{
   if(Form11==NULL){Form11 = new TForm11(NULL);}
}
//---------------------------------------------------------------------------
void __stdcall Okno_Destroy()
{
   if(Form11!=NULL){delete Form11; Form11=NULL;}
}
//---------------------------------------------------------------------------
void __stdcall Okno_Show()
{
   if(Form11!=NULL)Form11->Show();
}
//---------------------------------------------------------------------------


plik roboUnit1.cpp
Kod: Zaznacz cały
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "roboUnit1.h"
#include "roboUnit2.h"
#include "roboUnit3.h"
#include "okno.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
   : TForm(Owner)
{
Okno_Create();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
Okno_Destroy();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button11Click(TObject *Sender)
{
Okno_Show();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Form2->Show();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
Form3->Show();
}
//---------------------------------------------------------------------------


Jestem ciekaw czy to ja popełniam jakiś błąd, czy opcje kompilacji muszą być jakoś specjalnie dobrane, czy to może wina środowiska BDS2006. Może ktoś spróbuje to przekompilować w innym środowisku. Byłbym bardzo wdzięczny.
I jeszcze jedno. Chciałbym aby biblioteka była załadowana przy starcie programu i zwolniona dopiero po jego zamknięciu, tak aby obiekt Form11 był powołany na początku i był aktywny przez cały czas trwania programu (przecież nie ma nic w tym złego).
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
Avatar użytkownika
bodjanski
Bladawiec
Bladawiec
 
Posty: 10
Dołączył(a): wtorek, 23 listopada 2010, 18:31
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Windows XP
Kompilator: BDS2006
Gadu Gadu: 0
    Windows XPOpera

Re: DLL i Form1 cz.2

Nowy postprzez Cyfrowy Baron » sobota, 4 grudnia 2010, 16:31

Twój wywód jest mocno niezrozumiały.
W serwisie Cyfrowy Baron w dziale: teoria -> Tworzenie biblioteki DLL, opisałem sposób tworzenia i podłączania biblioteki w sposób statyczny, czyli biblioteka jest ładowana razem z programem, wymagany jest plik LIB biblioteki, oraz w sposób dynamiczny, biblioteka jest ładowana w dowolnym momencie, plik LIB jest zbędny. Przykłady pokazują jak wywołać z biblioteki okno 'O programie', były opracowane w środowisku C++Builder 6 i nie stwierdziłem żadnego z opisywanych przez Ciebie problemów.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL i Form1 cz.2

Nowy postprzez bodjanski » sobota, 4 grudnia 2010, 20:02

Drogi kolego Cyfrowy Baron

Nie mam cienia wątpliwości, że twoja wiedza przerasta wiedzę wszystich uczestników tego forum razem wziętych. Ale zamiast odpowiadać w stylu "Nie ważne jakie jest twoje podejście - przeczytaj jak ja to zrobłem, bo zrobiłem to w jedynie słuszny sposób", to lepiej w ogóle nie odpowiadać i olać post.
Proszę nie obraź się, ale namęczyłem się a ty nie patrząc na moje kody piszesz, że nie stwierdziłeś opisanych przeze mnie problemów. No jak mogłeś stwierdzić jeśli zrobiłes to zupełnie inaczej.
Nie chcę się rozpisywać ale nowa forma musi być powołana w konstruktorze i skasowana w zdarzeniu OnClose aplikacji. W twoim przykładzie powołujesz i kasujesz obiekt w zdarzeniu od przycisku, czyli zupełnie inaczej (klick i obiekt był a potem znikł). Ważne jest też aby nie ładować biblioteki dynamicznie (to przecież nie jest zabronione).

Oba projekty zamieściłem w załaczniku oknodll.zip. Jeśli masz czas i chęci to możesz zerknąć na te projekty, pochylić się nad nimi i przekompilować w twoim środowisku. Najprościej jest uruchomic exe-ka (jeśli jest ok. to może coś mi się pobaboliło w systemie operacyjnym i aplikacje mi się dziwnie zachowują).

Nie chodzi o to, żeby zrobić to inaczej. Chodzi o to, żeby pokazać gdzie jest błąd.
Avatar użytkownika
bodjanski
Bladawiec
Bladawiec
 
Posty: 10
Dołączył(a): wtorek, 23 listopada 2010, 18:31
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Windows XP
Kompilator: BDS2006
Gadu Gadu: 0
    Windows XPOpera

Re: DLL i Form1 cz.2

Nowy postprzez Cyfrowy Baron » sobota, 4 grudnia 2010, 23:29

Odesłałem Ciebie do porady byś sobie popatrzył jak to trzeba robić, ale Ty oczywiście nie zadałeś sobie tego trudu i od razu założyłeś, że nie o To Tobie chodzi. To był tylko przykład pokazujący jak to można zrobić, a nie jak należy to zrobić, więc można go sobie modyfikować do własnych potrzeb. Co więcej przykład był tworzony w środowisku C++Builder 6, więc jest najbliższy Twojemu środowisku.

Testowałem Twój projekt w C++Builder 2010 i nie stwierdziłem żadnych błędów. Zarówno bibliotekę jak i aplikację skompilowałem razem z bibliotekami ('Linkier \ Use dynamic RTL' oraz 'Packages \ Build with runtime packages) co nie ma żadnego znaczenia, jeżeli chodzi o działanie projektu. Nie mogłem uruchomić Twojego projektu, gdyż nie skompilowałeś go razem z bibliotekami.

okno z biblioteki dll manifestuje się jako osobna aplikacja na pasku zadań


To naturalne, przecież to okno nie jest częścią aplikacji, ustaw styl okna na bsToolWindow, a zniknie z paska zadań.

2) okno aplikacji nie chce się minimalizować lub nie 'przebija' się przez inne okna
3) inne okna aplikacji też pojawiają się na pasku zadań jako osobne etykiety
4) przy zamykaniu aplikacji powstaje błąd "access violations"


Żadne z tych zdarzeń nie ma miejsca.
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL i Form1 cz.2

Nowy postprzez polymorphism » niedziela, 5 grudnia 2010, 12:34

KOD cpp:     UKRYJ  
void __stdcall Okno_Create()
{
   if(Form11==NULL){Form11 = new TForm11(NULL);}
}

Hmm, a nie jakoś tak przypadkiem:
KOD cpp:     UKRYJ  
if(!Form11)
{
        Application->Handle = /* uchwyt okna głównego aplikacji */
        Form11 = new TForm11(Application);
}

:?:
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL i Form1 cz.2

Nowy postprzez bodjanski » niedziela, 5 grudnia 2010, 17:49

Dzięki Cyfrowy Baron. Właśnie chciałem żeby ktoś przekompilował to na innym komputerze. Jeśli mówisz, że u ciebie wszystko ładnie działa, to znaczy, że problem leży albo w moim kompilatorze albo w moich windowsach. Ja niestety wciąż obserwuje te babole z punktów 1 do 4 (... ok 2 do 4, jeśli to okienko z dll ma być na pasku zadań)
Przeproszam za emocje, ale jeśli człowiek siedzi cały dzień przed komputerem i cały czas coś się baboli, to można się zdenerwować :)
Avatar użytkownika
bodjanski
Bladawiec
Bladawiec
 
Posty: 10
Dołączył(a): wtorek, 23 listopada 2010, 18:31
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Windows XP
Kompilator: BDS2006
Gadu Gadu: 0
    Windows XPOpera

Re: DLL i Form1 cz.2

Nowy postprzez Cyfrowy Baron » niedziela, 5 grudnia 2010, 19:24

W swoim ostatnim poście w załączniku zamieściłem program wraz z biblioteką skompilowany przeze mnie w środowisku C++Builder 2010. Dziś dla pewności przetestowałem ten program na dwóch komputerach z systemem Windowx XP Pro SP2. Program działa prawidłowo, nie występuje żaden opisywanych przez Ciebie objawów. Jeżeli program z tego załącznika nie działa prawidłowo u Ciebie, to oznacza, że masz uszkodzone środowisko Windows.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL i Form1 cz.2

Nowy postprzez bodjanski » niedziela, 5 grudnia 2010, 20:33

Tak... w takiej postaci u mnie też działa (pliki ważą ponad 900KB każdy). Kluczową sprawą jest opcja 'Packages \ Build with runtime packages'. Jeśli ta opcja jest zaznaczona w obu projektach (wtedy pliki mają po kilkadziesiąt KB tylko), to wtedy dzieją się u mnie te dziwne rzeczy.
Avatar użytkownika
bodjanski
Bladawiec
Bladawiec
 
Posty: 10
Dołączył(a): wtorek, 23 listopada 2010, 18:31
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Windows XP
Kompilator: BDS2006
Gadu Gadu: 0
    Windows XPOpera

Re: DLL i Form1 cz.2

Nowy postprzez Cyfrowy Baron » poniedziałek, 6 grudnia 2010, 00:04

Jeżeli chcesz by Twoje programy działały na innych komputerach niż Twój z zainstalowanym środowiskiem C++Builder w Twojej wersji, to musisz je kompilować razem z bibliotekami, co oczywiste zwiększy rozmiar plików wykonywalnych i bibliotek. Bez kompilowania razem z bibliotekami, będziesz musiał dystrybuować aplikację dołączając do niej biblioteki. Niezależnie jednak od tego, czy skompiluję projekt z bibliotekami czy bez on u mnie działa bezbłędnie.

Ja u siebie nie mogłem uruchomić pliku exe, który dołączyłeś do archiwum, gdyż w moim środowisku C++Builder 2010 nie występują biblioteki, których tak skompilowany przez Ciebie program potrzebuje.

Nie rozumiem już istoty Twojego problemu.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL i Form1 cz.2

Nowy postprzez bodjanski » poniedziałek, 6 grudnia 2010, 09:48

biblioteki z BDS2006
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
Avatar użytkownika
bodjanski
Bladawiec
Bladawiec
 
Posty: 10
Dołączył(a): wtorek, 23 listopada 2010, 18:31
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Windows XP
Kompilator: BDS2006
Gadu Gadu: 0
    Windows XPOpera

Re: DLL i Form1 cz.2

Nowy postprzez Cyfrowy Baron » poniedziałek, 6 grudnia 2010, 11:54

Sprawdziłem Twoją komplikację, z Twoimi bibliotekami i jedyny błąd jaki stwierdziłem, to że główne okno programu nie minimalizuje się, poza tym nie występuje żadnej inny błąd. Jeszcze nie tak dawno używałem środowiska BDS2006 i nie zauważyłem podobnych błędów. W przypadku bibliotek postępowałem co prawda nieco inaczej niż Ty. Główna różnica polegała na tym, że w przypadku bibliotek tworzyłem okno dynamicznie trochę inaczej, gdybym to robił tak jak ty, to postąpiłbym pewnie tak:

KOD cpp:     UKRYJ  
#pragma argsused

TForm11 *dll_Form;

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)
{
        return 1;
}
//---------------------------------------------------------------------------
void Okno_Create(void)
{
        if(dll_Form == NULL)
        {
        dll_Form = new TForm11(NULL);
        }
}
//---------------------------------------------------------------------------
void Okno_Destroy(void)
{
        if(dll_Form != NULL)
        {
         delete dll_Form;
         dll_Form = NULL;
        }
}
//---------------------------------------------------------------------------
void Okno_Show(void)
{
        if(dll_Form != NULL) dll_Form->Show();
}
//---------------------------------------------------------------------------


To pewnie niczego nie zmieni.
Kiedyś zetknąłem się z podobnym problemem w przypadku obcej biblioteki, a główny problem polegał na tym, że nagłówek funkcji nie mógł być bez argumentów, jeżeli funkcja nie pobiera argumentów to podaje się typ pusty void.

KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------
void __stdcall Okno_Create( void )
{
        if(Form11 == NULL)
        {
        Form11 = new TForm11(NULL);
        }
}
//---------------------------------------------------------------------------
void __stdcall Okno_Destroy( void )
{
        if(Form11 != NULL)
        {
         delete Form11;
         Form11=NULL;
        }
}
//---------------------------------------------------------------------------
void __stdcall Okno_Show( void )
{
        if(Form11 != NULL)Form11->Show();
}
//---------------------------------------------------------------------------


Przeprowadziłem u siebie testy z Twoim projektem kompilując go bez bibliotek i problem z minimalizacją okna głównego w takiej sytuacji u mnie również występuje, na co wcześniej nie zwróciłem uwagi. Problem jest niezależnie od tego, czy zrobię to po Twojemu czy po swojemu. Stwierdziłem jednak, że problem dotyczy tylko biblioteki DLL, gdy jest skompilowana bez bibliotek.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL i Form1 cz.2

Nowy postprzez bodjanski » poniedziałek, 6 grudnia 2010, 14:03

Wszystkie problemy, które opisałem znikają, jeśli bibliotekę okno.dll podłaczam dynamicznie np. w konstruktorze przed wywołaniem funkcji OknoCreate() (wskaźniki do funkcji z dll-ki zadeklarowane jako globalne). Wtedy nawet okno z dll-ki nie pojawia się na pasku zadań jako osobna ikonka (i nie musi mieć właściwości bsToolWindow). I nie ma też żadnego znaczenia z jakimi opcjami jest skompilowana biblioteka okno.dll.
No ale czy ktoś od Borlanda (czy teraz Embarcadero) powiedział, że zabronione jest statyczne podłaczanie dll-i, które zawierają komponenty VCL i skompilowane są bez bibliotek BPL (czyli z opcją "Build with runtime packages")? To było pytanie retoryczne.
Avatar użytkownika
bodjanski
Bladawiec
Bladawiec
 
Posty: 10
Dołączył(a): wtorek, 23 listopada 2010, 18:31
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Windows XP
Kompilator: BDS2006
Gadu Gadu: 0
    Windows XPOpera


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Biblioteki i komponenty

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 8 gości