selbst erstellte DLL und UseGadgetList darin

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Makke
Beiträge: 156
Registriert: 24.08.2011 18:00
Computerausstattung: AMD Ryzen 7 5700X - AMD Radeon RX 6800 XT - 32 GB DDR4 SDRAM
Wohnort: Ruhrpott
Kontaktdaten:

selbst erstellte DLL und UseGadgetList darin

Beitrag von Makke »

Hallo zusammen,

ich habe (eigentlich für Linux, soll aber auch unter WIndows laufen) eine DLL erstellt die Animationen auf einem ImageGadget abspielt. Sinn und Zweck ist die GUI für unterschiedliche Programme grafisch etwas aufzuhübschen, ohne den ganzen Code in andere Programme zu übernehmen sondern einfach nur die DLL einzubinden und die Animationen daraus zu starten (die Grafiken sind ebenfalls in der DLL enthalten).

Ich wollte einfach folgenden Befehl zur Verfügung stellen: AnimImageGadget(WindowID, x, y, AnimName, fps, width, height)

Innerhalb der Procedure benutze ich dann UseGadgetList(windowID), aber genau das funktioniert nicht. Zum besseren Verständnis mal der Code wie ich die DLL/so einbinde:

Code: Alles auswählen

Import "animatedimages.so"
  AnimImageGadget_Initialize()
  AnimImageGadget.i(WindowID.i, Handle.i, X.l, Y.l, AnimName.s, Width.l=0, Height.l=0, DelayBetween.l=0, Decoration.l=0)
  AnimImageGadget_GetLastError() ;??? .s
EndImport

If OpenLibrary(0, "animatedimages.so")
  CallFunction(0, "AnimImageGadget(Handle.i, X.l, Y.l, AnimName.s, Width.l=0, Height.l=0, DelayBetween.l=0, Decoration.l=0)")
  CloseLibrary(0)
EndIf

Define.l n
AnimImageGadget_Initialize()
If OpenWindow(0, 0, 0, 470, 90, "TEST", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  For n = 0 To 6
    Select Random(2)
      Case 0 : Debug AnimImageGadget(WindowID(0), n, n*64+10, 10, "folder_compare_anim", 0, 0, 0, #PB_Image_Border) : Debug AnimImageGadget_GetLastError()
      Case 1 : Debug AnimImageGadget(WindowID(0), n, n*64+10, 10, "folder_search_anim", 0, 0, 0, #PB_Image_Border)  : Debug AnimImageGadget_GetLastError()
      Case 2 : Debug AnimImageGadget(WindowID(0), n, n*64+10, 10, "wait_anim", 0, 0, 0, #PB_Image_Border)           : Debug AnimImageGadget_GetLastError()
    EndSelect
    Delay(100)
  Next
EndIf

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
Wenn ich das starte, erhalte ich leider keine schönen Animationen sondern ein leeres Fenster mit folgenden Fehlermeldungen (Achtung Linux):

Code: Alles auswählen

[12:02:12] Warte auf den Start des Executable...
[12:02:12] Executable-Typ: Linux - x64  (64bit, Unicode, Purifier)
[12:02:12] Executable gestartet.
[12:02:12] [WARNING] test_animimages2.pb (Zeile: 17)
[12:02:12] [WARNING] Gtk (CRITICAL): IA__gtk_fixed_put: assertion 'GTK_IS_FIXED (fixed)' failed
[12:02:12] [WARNING] test_animimages2.pb (Zeile: 17)
[12:02:12] [WARNING] Gtk (CRITICAL): IA__gtk_widget_realize: assertion 'GTK_WIDGET_ANCHORED (widget) || GTK_IS_INVISIBLE (widget)' failed
[12:02:12] [Debug] 40463808
usw...
Der Rückgabewert der DLL ist das Gadget Handle bzw. die ID. AnimImageGadget_GetLastError() sollte eigentlich einen String liefern, das funktioniert aber nicht mit Import, muss ich da einen Pointer zurück liefern ?

Ich bin für alle Tips und Lösungsansätze dankbar.
---
Windows 11 (64 bit)
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Re: selbst erstellte DLL und UseGadgetList darin

Beitrag von Bisonte »

Ohne den Code der DLL/so zu sehen wird das schwierig.
Allerdings fällt mir zumindest spontan auf :

(Ich kann nur von Windows aus sprechen...)
Importiert werden eigentlich nur .lib Dateien, nicht die DLL.
Dann öffnest du zusätzlich noch die DLL und rufst (zumindest willst du das wohl) eine
Funktion auf. Callfunction kann so aber nicht funktionieren. (Völlig falscher Aufruf)

Desweiteren muss (wenn die DLL geladen wird) die DLL solange "Open" sein, wie die
Funktionen daraus benutzt werden. Wenn man sie schliesst und danach versucht eine Funktion aufzurufen ist essig...

Ausserdem solltest du (beim DLL nutzen) lieber Prototypes verwenden.
Und die "optionalen" Parameter funktionieren so leider auch nicht.
Da muss für jeden Parameter eine eigene Prozedur in der DLL für existieren, ODER
Man hat eine "Wrapper" Prozedur, die dann fehlendes einträgt.
(Wobei ich glaube mit Prototypes geht das schon...)
Ich versuche mal ein kurzes Beispiel zu basteln, das zeigt was ich meine...

Edit : Hier die Beispiele :

Die Dll ist mit Unicode kompiliert

Code: Alles auswählen

;: TestDLL Windows

Global ReturnString.s = ""

ProcedureDLL BGadget(WindowID, x, y, AnimName.s, fps, width, height)
  
  Protected Result = #False
  Protected OldGadgetList
  
  If IsWindow_(WindowID)
    OldGadgetList = UseGadgetList(WindowID)
    
    Result = ButtonGadget(#PB_Any, x, y, width, height, AnimName)
    
    Result = GadgetID(Result)
    
    UseGadgetList(OldGadgetList)
  EndIf
  
  ProcedureReturn Result
  
EndProcedure
; - Eine "Private" Prozedur, die von aussen nicht erreichbar ist.
Procedure.s BStringFunction(String1.s, String2.s)
  
  Result.s = String1 + "..." + String2 + "...!"
  ProcedureReturn Result
  
EndProcedure
; - Und hier nun die Prozedur, die von aussen erreichbar sein soll
ProcedureDLL.s BString(String1.s, String2.s)
  
  ReturnString = BStringFunction(String1, String2)
  ProcedureReturn ReturnString
  
EndProcedure


das benutzende Programm....

Code: Alles auswählen

Prototype proto_BGadget(WindowID, x, y, AnimName.p-Unicode, fps = 10, width = 100, height = 20)
;                                       ------------------ Automatische Umwandlung weil ich die DLL in unicode kompiliert habe
Prototype proto_BString(String1.p-Unicode, String2.p-Unicode)

If Not OpenLibrary(0, "Test_Dll.dll") : End : EndIf

Global BGadget.proto_BGadget = GetFunction(0, "BGadget") ; BGadget Global Verfügbar machen
Global BStringFunction.proto_BString = GetFunction(0, "BString") 

Procedure.s BString(String1.s, String2.s)
  
  Protected Result, String.s = ""
  
  Result = BStringFunction(String1, String2)
  String = PeekS(Result, -1, #PB_Unicode)
  
  ProcedureReturn String
  
EndProcedure

If Not BGadget : End : EndIf ; Check ob das zuweisen funktioniert hat

OpenWindow(0, 0, 0 , 640, 480, "Test", #PB_Window_SystemMenu)

BGadget(WindowID(0), 10, 10, "Hallö", 0, 300)
Debug BString("Hallo","Du Da")

Repeat
  Event = WaitWindowEvent()
  
Until Event = #PB_Event_CloseWindow
Oder per Import

Code: Alles auswählen

Import "Test_Dll.lib"
  BGadget(WindowID, x, y, AnimName.p-Unicode, fps = 10, width = 100, height = 20) As "BGadget"
  BStringFunction(String1.p-Unicode, String2.p-Unicode) As "BString" 
EndImport

Procedure.s BString(String1.s, String2.s)
  
  Protected Result, String.s = ""
  
  Result = BStringFunction(String1, String2)
  String = PeekS(Result, -1, #PB_Unicode)
  
  ProcedureReturn String
  
EndProcedure

OpenWindow(0, 0, 0 , 640, 480, "Test", #PB_Window_SystemMenu)

BGadget(WindowID(0), 10, 10, "Hallö", 0)
Debug BString("Hallo","Du Da")

Repeat
  Event = WaitWindowEvent()
  
Until Event = #PB_Event_CloseWindow
Und hiermit sage ich, daß die optionalen Parameter dann per Prototype auch funktionieren ;)
Zuletzt geändert von Bisonte am 25.08.2014 16:29, insgesamt 2-mal geändert.
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: selbst erstellte DLL und UseGadgetList darin

Beitrag von STARGÅTE »

In deinem Beispielcode vermisschen sich zwei sachen (wie Bisonte schon erklärt).

Import : EndImport importiert Funktionen direkt in die eigene Kompilierung. Ein OpenLibrary ist nicht nötig!
OpenLibrary() öffnet eine Library außerhalb des Programms. Dann ist kein Import nötig.

Allgemein gilt: Du kannst in der DLL nicht auf die "internen" Ressourcen von PB-Funktionen zugreifen.
Das Nummern/ID System von PB ist ein abgeschlossenes System was nicht DLL-Übergreifen funktioniert.
Ein Image/Sprite/Window usw. welches im MAIN erstellt wurde kann nicht in der DLL benutzt werden und anders rum.

Nur System-Handels sind Übergreifend oder eigene definierte Ressourcen.

Und ja, Rückgabewerte von DLLs sind immer nur Ganz- oder Fließkommazahlen.
Also muss vom String der Pointer zurückgegeben werden (Er muss auch Global sein!) und im Main mit PeekS() gelesen werden.
Auchtung hier Ascii/Unicode.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: selbst erstellte DLL und UseGadgetList darin

Beitrag von mk-soft »

Aus DLL Gadgets erstellen geht genau so wenig wie Gadgets aus Thread zu erstellen.
Am besten an das Hauptprogramm eine Nachricht senden um Gadgets zu erstellen.

Hab hier mal ein Beispiel. Muss noch mit UsesGadgetList angepasst werden.

http://www.purebasic.fr/english/viewtop ... nt#p401150
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Re: selbst erstellte DLL und UseGadgetList darin

Beitrag von Bisonte »

hab das DLL-Beispiel noch um die Stringrückgabe (die eigentlich keine ist) erweitert.

@mk-soft: Das Problem bei PostEvent() ist, dass dort ebenfalls die PB Nummern als Parameter gefragt sind, und das ist,
wenn man auf diese nicht zugreifen kann, recht schwierig.

Unter Windows kann ich SendMessage_() oder PostMessage_() verwenden, aber bei den anderen OS wüsst ich jetzt nicht wie
ich was an das entsprechende Fenster schicken sollte....
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: selbst erstellte DLL und UseGadgetList darin

Beitrag von ts-soft »

@Bisonto
Wie wäre es, wenn Du dem link von mk-soft folgst :mrgreen:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: selbst erstellte DLL und UseGadgetList darin

Beitrag von mk-soft »

Bisonte hat geschrieben: @mk-soft: Das Problem bei PostEvent() ist, dass dort ebenfalls die PB Nummern als Parameter gefragt sind, und das ist,
wenn man auf diese nicht zugreifen kann, recht schwierig.
Das Hauptprogramm sollte schon wissen welche Gadgetlist verwendet werden muss.
Nach dem erstellen des Gadgets aus dem Hauptprogramm wird die GadgetID (#PB_Any) zurückgeliefert. Diese kann in der DLL dann weiter verwendet werden.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Re: selbst erstellte DLL und UseGadgetList darin

Beitrag von Bisonte »

ts-saft hat geschrieben:@Bisonto
Wie wäre es, wenn Du dem link von mk-soft folgst :mrgreen:
Bin ich, lieber ts-saft :mrgreen: ...
und dort sah ich "nur" PostEvent() um Events zu senden.
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: selbst erstellte DLL und UseGadgetList darin

Beitrag von ts-soft »

Und ich sah dort: SendEvent
Ist wohl für Threads, aber könnte auch mit DLLs funktionieren.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Makke
Beiträge: 156
Registriert: 24.08.2011 18:00
Computerausstattung: AMD Ryzen 7 5700X - AMD Radeon RX 6800 XT - 32 GB DDR4 SDRAM
Wohnort: Ruhrpott
Kontaktdaten:

Re: selbst erstellte DLL und UseGadgetList darin

Beitrag von Makke »

Danke für Eure Tips, Erklärungen und Beispiele. Ich werde die Sache von Bisonte mal genauer unter die Lupe nehmen und schauen was geht. Melde mich hier wieder.
---
Windows 11 (64 bit)
Antworten