Dll erstellen und mit AutoIt nutzen - FreeBasic Tutorial

  • Wer AutoIt beherrscht und sich ein wenig mit Messages und Objekten befasst hat, der wird sich an PowerBASIC auch keinen Zahn ausbrechen und kann erstaunliche Ergebnisse erzielen.

    Hier mal ein Beispiel für den Syntax:

    Ist sehr vertraut, nicht? ;). Hier mal ein kleines Beispiel für eine Dll. Diese gibt einfach nur eine MsgBox mit dem übergebenen Parameter aus, und den Sinn des Lebens zurück, 42 ;)

    Und zum Aufrufen in AutoIt:

    [autoit]

    $hDll = DllOpen("MyDLL.dll")
    $aResult = DllCall($hDll, "long", "MyFunction1", "long", 1234)
    MsgBox(64, "minx", "Die Dll hat folgendes geschrieben: "&$aResult[0])

    [/autoit]

    Oder fürs neue AutoIt:

    [autoit]

    MsgBox(64, "minx", "Die Dll hat folgendes geschrieben: "& DllCall(DllOpen("MyDLL.dll"), "long", "MyFunction1", "long", 1234)[0] )

    [/autoit]


    Keine AHnung ob PB inzwischen kostenlos ist, ich habe es von meinem Vater. Es ist wirklich wahnsinnig schnell. Zum Beispiel im direkten Vergleich die Graphics-Befehle von Au3 und PB. Es sind die gleichen, nur das es bei PB mehr gibt, und das sie eine unerhörte Geschwindigkeit haben. Klar kann man auch in PB GDI(+) nutzen, aber das ist absolut nicht nötig. Es gibt übrigens Graphicbefehle die Bildbearbeitung ermöglichen, die vermisse ich bei Au3 sehr.

    Der ganze Source und die Dll ist hier .

    So long!

  • Der 114 Tage Hinweis wurde hiermit von mir berücksichtigt^^ (gesehen hab ich ihn :D)

    Da ich AutoIt verwöhnt bin, bin ich es gewohnt mit Dlls wie Folgt umzugehen.
    $Handle = DllOpen(xyz)
    $Result = DllCall($Handle, x, y, z)
    DllClose($Handle)

    In Basic scheint das etwas anderst zu funktionieren.
    (Und wie bekomme ich möglichst einfach ein Windows Fenster (wie GuiCreate))

    Ich hätte gerne sowas in der Art (wie im Spoiler) in FB (Komplett alleinstehend ohne AutoIt zum Aufrufen).

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_Startup()

    [/autoit] [autoit][/autoit] [autoit]

    Global $R = 255, $G = 128, $B = 64
    Global $hGUI = GUICreate('Test', 200, 200)
    Global $hGFX = _GDIPlus_GraphicsCreateFromHWND($hGUI)

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    While Not (GUIGetMsg() = -3)
    _GDIPlus_GraphicsClear($hGFX, '0xFF' & Hex(Int($R),2) & Hex(Int($G),2) & Hex(Int($B),2))
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_GraphicsDispose($hGFX)
    _GDIPlus_Shutdown()

    [/autoit]


    .
    .

  • Mit Freebasic (PNG per GDI+ in GUI) Quelle

    Spoiler anzeigen

    Geht als Anregung durch ^^. Für GUIs allgemein siehe hier

  • Sehr schön. Jetzt ist das schonmal geklärt.
    Dann habe ich noch eine Frage.

    Code
    Do Until( GetMessage( @wMsg, null, 0, 0 ) = 0 )
      TranslateMessage( @wMsg )
      DispatchMessage( @wMsg )
    Loop


    Dieser Code reguliert scheinbar wie GuiGetMsg die Geschwindigkeit. (CPU ist bei mir bei 0% im Leerlauf beim Ausführen).
    Existiert auch ein EventMode in Basic ?

  • Mittlerweile gibt es FreeBasic 1.0

    Damit kann man nun endlich auch X64 Dll´s erzeugen.


    Man benötigt folgende Dateien (http://www.freebasic.net/get:(
    FreeBASIC-1.00.0-win64.zip
    FreeBASIC-1.00.0-win32.zip (nur, wenn man auch X86 komiplieren will)

    Zuerst entpackt man FreeBASIC-1.00.0-win64.zip in den gewünschten Installationsordner.
    Dann entpackt man FreeBASIC-1.00.0-win32.zip in ein temporäres Verzeichnis und kopiert die Ordner bin\win32 und lib\win32 in die entsprechenden Ordner der Installationsversion.

    Im Prinzip funktioniert alles noch so, wie im ersten Post beschrieben (zumindest sollte es)
    Allerdings muss man weitere Compilerswitches beachten:

    z.B.: Wenn man InlineASM verwendet, dann muss man "-asm intel" verwenden.
    Wenn man X86 erstellen will, braucht man den Switch "-target win32"

  • Gibt es eine Möglichkeit über den Dllcall auch Strings zu übergeben und zurückzugeben ?
    Irgendwie bekomme ich das nicht hin, mit Integer Werten klappt es ohne Probleme.

    Freebasic Code:

    Code
    Extern "Windows-MS"
    Function stringtest(iX As String)As String Export
    
    	Return iX
    
    End Function
    End Extern


    Autoit Code:

    Code
    $hDll = DllOpen("stringtest.dll")
    $aResult = DllCall($hDll, "str", "stringtest", "str", "test")
    MsgBox(0,"",$aResult[0])
  • hänge mal deine dll mit an...

  • Ich nutze selber kein FreeBASIC, allerdings habe ich trotzdem eine Vermutung. Strings sind ja eigentlich nichts anderes als Arrays von Char-Elementen. Wenn man einen String an eine Funktion übergibt (und hier erleichtert AutoIt uns die Arbeit), übergibt man eigentlich nur die Adresse des ersten Char-Elements. Die Funktion liest dann ab dieser Adresse so lange den Speicher aus, bis sie auf das NUL-Zeichen (ASCII 0) stößt. FreeBASIC nimmt einem aber - vermutlich - nicht so viel Arbeit ab wie AutoIt. Dazu kommt auch, dass FreeBASIC generell zwischen Variablen und Pointern unterscheidet, AutoIt kennt ja keine Pointer. Daher würde ich vermuten, dass man aus FreeBASIC heraus auch wieder einen Pointer übergeben muss, den AutoIt dann intern als String interpretiert und weiterverarbeitet. Eine schnelle Google-Suche ergibt, dass dazu ein @ vor den Variablennamen gesetzt werden muss. Vielleicht ist's das ja, keine Ahnung.

    Gruß

  • Der Datentyp String arbeitet grundsätzlich anders als der in AutoIt. Wenn du per DllCall() einen String übergibst, ist dieser Null-terminierend, das bedeutet dass das Letzte Zeichen immer das Null-Zeichen (Chr(0)) ist. FreeBASIC speichert aber zu jedem String dessen Länge ab. Dadurch kann FreeBASIC Strings dynamisch verwalten und sogar das Null-Zeichen mitten in einen String abspeichern und ausgeben. Du benötigst den Datentyp ZString welcher die gleiche Arbeitsweise wie von den gewohnten Strings entspricht. Dann sollte das auch so funktionieren wie du dir das vorstellst. Jedoch ist zu beachten dass du einen ZString nicht einfach returnen kannst, lediglich den Pointer dazu kannst du zurückgeben:

    Code
    Extern "Windows-MS"
    Function stringtest(iX As ZString) As ZString Ptr Export
    
    	Return @iX
    
    End Function
    End Extern


    LG. Make :)

  • Du kannst den gleichen AutoIt-Code nutzen den du oben gepostet hast.

    Zu den Datentypen, ich versuche es einmal anders zu erklären:
    Wenn du von AutoIt aus per DllCall() einen String versendest, hängt AutoIt automatisch noch das Null-Zeichen hinten dran. Aus 'stringtest' wird demnach 'stringtest' & Chr(0). In FreeBASIC ist aber der Aufbau anders, die Strings die dort genutzt werden speichern noch die Länge mit ab. Vereinfacht gesagt wird dort 'stringtest' zu (Länge: 10 Zeichen | String: 'stringtest'). Intern werden die Strings also unterschiedlich gespeichert, wenn du FreeBASIC nun sagst es soll als Datentyp String verwenden, dann versucht es natürlich die übergebene Zeichenkette in seiner eigenen Struktur für Strings zu lesen. Das wäre so als ob du einen Deutschen einen arabischen Text geben würdest und sagst er solle diesen einfach mal vorlesen. :D

    Der Datentyp ZString hingegen entspricht der Struktur wie der, die DllCall() nutzt. Gibt es sonst noch Fragen? :)