Cześć,
czy ktoś mógłby podać przykład jakiegoś open-sourceowego IDE pisanego w Delphi? Nie mogę wydumać sensownej architektury pluginów dla mojego projektu, chętnie popatrzyłbym jak inni rozwiązali problem ...
Z góry dzięki!
Juhas rzuć linkiem.
Ja uważam że jest to mało znane w naszych kręgach ze względu na jedną sprawę. Programiki są nieduże a rozszerzając jakiś program dodatkowo poprawia się błędy, które w nim powstają.
Moim zdaniem należy zrobić coś w stylu zewnętrznej biblioteki z funkcjami programu i ją modyfikować wówczas ona będzie tym pluginem. Jeśli chodzi o jego konstrukcję to też mnie ciekawi :)
W projekcie SharpE jest sporo pluginów :)
Juhas, bądź tak miły i daj linka jakiegoś :) Zwróć uwagę że wiem co chcę osiągnąć - piszę własne IDE dla kilku języków programowania, i zamiast upychać funkcje do głównego programu chciałbym by były to pluginy.
Przykładowo, w programie mamy obsługę otwierania plików do edycji [używając SynEdita oczywiście ;) ]. Potrzebne będą podpowiedzi do kodu, i to już bym chciał by było realizowane przez plugin. Podobnie debugger - jest zaimplementowany w programie, ale fajnie by było gdyby pluginy miały do niego dostęp - w ten sposób można by np po stronie plugina zrealizować podpowiedzi do kodu w czasie debuggowania (podgląd zmiennych itp).
Czemu tak się upieram przy pluginach? Otóż z doświadczenia wiem że w jednym programie to już będzie za dużo ... po to przepisuje program od nowa by uniknąć starych błędów. Między innymi właśnie tego ...
Obecnie jestem w trakcie implementowania prostego (na razie) systemu pluginów opartego o COMy. Tyle tylko, że niestety - aby udostępnić jakąś część programu muszę napisać wrappera - u mnie zrealizowałem to w ten sposób (kawałek [pseudo]kodu mówi więcej niż 1000 słów)
type
TSDKEditor = class(TObject, ISDKEditor) //
private
fEditor: TSynEdit;
public
function GetXY: TPoint;
end;
Tak więc w momencie gdy plugin chce dostęp do np aktywnego pliku, z odpowiedniego serwisu udostępnionego przez aplikację wywołuje metodę "GetActiveEditor" która tworzy obiekt TSDKEditor ustawiając mu zmienną fEditor - i zwraca to jako interfejs ISDKEditor.
Plugin sobie cośtam wywołuje, obiekt zaś wykonuje odpowiednie akcje na fEditor.
W teorii proste, w praktyce - pisanie wrapperów to mordęga. A później jeszcze debuggowanie, dbanie o pamięć ... masakra [glowa]
Stąd chciałbym podpatrzeć jakąś metodę "jak to robią profesjonaliści"
adydan - w moim przypadku akurat to nie jest potrzebne, główny program raczej ma docelowo być mocno okrojony ...
PS. temat pisałem ja tylko nie chciało mi się logować :P
Linkiem nie rzucę, bo nie pamiętam. Ale autor strony to zdaje się Grzegorz Skoczylas, czy Jerzy Skoczylas. Jakoś tak. Tak więc wpiszecie to w google i coś powinno wyjść :)
Są dwie metody pisania pluginów - z użyciem obiektów COM, lub z użyciem zwykłych dll.
Ja u siebie robię to za pomocą zwykłych dll, bo nie potrzebowałem obiektów COM.
Po krótce wygląda to tak, że jest interfejs, w którym są wszystkie metody jakie plugin musi posiadać.
Plugin udostępnia na zewnątrz(eksportuje) np. tylko jedną funkcję, która zwraca jego obiekt(zdaje sie jako interfejs) i od tej pory z poziomu programu głównego można się porozumiewać z pluginem. Ponadto można stworzyć drugi interfejs - interfejs aplikacji głównej, dzięki któremu plugin będzie mógł wtedy, kiedy potrzebuje wykonać jakąś operację w programie głównym(a konkretnej wywołać udostępnioną metodę z programu głównego).
Może trochę to niejasno napisałem, ale na stronie pana Skoczylasa jest całkiem ok opisane to. Z jakimiś tam przykładami. Pamiętam, że miałem na początku duże problemy ze zwróceniem obiektu pluginu do programu głównego(jakieś duże problemy z pamięcią), ale w końcu dałem se radę. Tak więc jak coś, to mogę służyć radą :D
Aha, ważna rzecz: NIE UŻYWAJCIE SHAREMEM, róbcie tak biblioteki, żeby chodziły bez tego. Bo z tego, co wiem, jeśli będzie inaczej zaprojektowane, no to pluginy będą mogłby być tylko pisane w Delphi, a nie o to chodzi :)
Tak więc głównie, zero używania stringów, tablic dynamicznych itp. tworzyw jako parametrów lub typów zwracanych funkcji.
Juhas, wprawdzie artykułu nie czytałem (zaraz przeczytam, dla zainteresowanych: http://gskoczylas.rekord.pl/index.php?page=http://gskoczylas.rekord.pl/Delphi/PlugIn_PL.php ) ale powiem Ci ze u mnie działa to teraz dokładnie identycznie jak opisane przez Ciebie rozwiązanie. Tyle że używam od dawna FastMM4 więc w kwestii ShareMem ... :]
Dla mnie ważnym problemem jest kwestia przechwytywania zdarzeń. Przykładowo, zmiana aktywnej zakładki w programie - i jak o tym powiadomić plugin?
Myślałem nad kilkoma rozwiązaniami, np implementowany po stronie plugina interfejs I...EventHandler, który byłby rejestrowany w programie - następnie wszystkie zarejestrowane w programie miałyby wywoływaną odpowiednią metodę...
a może coś na wzór windowsowych Messages z kilkoma parametrami? ...
andy-m: dzięki, znam :) ale to nie w tym rzecz, mi nie chodzi o kwestię ładowania bibliotek i udostępniania odpowiednich interfejsów. Mi chodzi o zaprojektowanie sensownej architektury...
migajek napisał(a)
Juhas, wprawdzie artykułu nie czytałem (zaraz przeczytam, dla zainteresowanych: http://gskoczylas.rekord.pl/index.php?page=http://gskoczylas.rekord.pl/Delphi/PlugIn_PL.php ) ale powiem Ci ze u mnie działa to teraz dokładnie identycznie jak opisane przez Ciebie rozwiązanie. Tyle że używam od dawna FastMM4 więc w kwestii ShareMem ... :]
FastMM to lepsza wersja ShareMem, a więc też nie powinieneś jej używać, jeśli chcesz mieć możliwość pisania pluginów w innych językach niż Delphi.
Dla mnie ważnym problemem jest kwestia przechwytywania zdarzeń. Przykładowo, zmiana aktywnej zakładki w programie - i jak o tym powiadomić plugin?
Mniej więcej tak jak napisałeś. Po prostu w odpowiednim momencie wywołujesz odpowiednią metodę w pluginie. Tylko teraz pytanie czy to ma być coś w sensie: "ActiveTabChanged", czy bardziej ogólnie "AnyChange" :P
W drugim przypadku oczywiście nie obejdzie się bez jakiś parametrów, ale to już Ty wiesz co potrzebujesz.
Juhas napisał(a)
FastMM to lepsza wersja ShareMem, a więc też nie powinieneś jej używać, jeśli chcesz mieć możliwość pisania pluginów w innych językach niż Delphi.
Zgadza sie, jest to lepszy manager pamieci dla Delphi :) fakt, uzywajac go nie moge przekazywac stringow, obiektow itp - ale wole chyba poswiecic inne jezyki (nie sadze by ktos chcial szybko pisac pluginy dla mojego programu) na rzecz wygody przy pisaniu modulow w Delphi :) a ze uzywam FastMM zamiast ShareMem to nie dotyczy mnie problem z borlandmm.dll (czy jak sie zwala ta biblioteczka) ... to mialem na mysli ;)
Tylko teraz pytanie czy to ma być coś w sensie: "ActiveTabChanged", czy bardziej ogólnie "AnyChange" :P
W drugim przypadku oczywiście nie obejdzie się bez jakiś parametrów, ale to już Ty wiesz co potrzebujesz.
Dokladnie, zapewne w przypadku "AnyChange" bym to rozwiazal tak jak w Windows Messages - ID zdarzenia, i kilka parametrow ;)
andy-m: owszem, to tak :) ale ja bardziej pytam o takie aspekty jak omawiane z Juhasem :P