Hilfe mit Aufruf von dll Funktion(en)

  • Hallo,

    vielleicht könnte mir bitte jemand helfen um Funktionen aus einer dll, die in Delphi geschrieben wurde, aufzurufen.
    Ich bin schon am verzweifeln warum das nicht klappt. Mit anderen dll's (z.B. System dll's) klappt es ohne Probleme.
    Da ich das für ein Projekt in meiner Arbeit brauche wäre ich für Hilfe sehr dankbar.
    Die dll kann ich öffnen und es ist mir auch möglich alle Funktionen (14) zu erreichen.

    Allerdings crashed AutoIt mit der Meldung: "AutoIT3.exe ended.rc:-1073741819" wenn ich die Ininitialisierungs Funktion (Procedure trxInitialize) der dll aufrufe.
    Die dll kann ich aus Copyrightgründen nicht mitgeben (kostet 750€)
    Vielleicht kann mir jemand sagen mit welchem Parametertyp ich diese dll-Funktion aufrufen muss.
    Ich versuche es schon seit zwei Tagen und steh jetzt total auf dem Schlauch.
    Vielen Dank im Voraus für eure Hilfe.

    Gruß, PixelStorm

    Hier einmal der AutoIt Code den ich benutze:

    [autoit]

    #include <APIErrors.au3>
    #include <Array.au3>
    #include <WinAPI.au3>
    #include <WinAPIReg.au3>
    #include <WinAPISys.au3>
    #include <WindowsConstants.au3>

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

    Global Const $trxCommOK = 0
    Global Const $trxCommNACK = 1
    Global Const $trxCommOutOfRange = 2
    Global Const $trxCommNoFile = 3
    Global $trxString = ""
    Global $NumberOfTRXunits = 0
    Global $AvailableTRXunits[256] = []

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

    InitTRX_01()
    InitTRX_02()

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

    Func InitTRX_01()
    Global $trxFunctions[14][2] = [["trxInitialize"],["trxIdentify"],["trxAttenuation"],["trxFrequency"],["trxPI"],["trxPS"],["trxTA"],["trxTP"], _
    ["trxEON_TA"],["trxEON_TP"],["trxEON_PS"],["trxLoadRDS"],["trxEAS"],["trxMode"]]
    _ArrayDisplay($trxFunctions, "$trxFunctions without Address")

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

    $handle_trxDLL = _WinAPI_LoadLibrary("trxRemote.dll")
    For $i = 0 To UBound($trxFunctions) - 1
    $trxFunctions[$i][1] = _WinAPI_GetProcAddress($handle_trxDLL, $trxFunctions[$i][0])
    Next
    _ArrayDisplay($trxFunctions, "$trxFunctions with Address")

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

    ConsoleWrite("Function: " & $trxFunctions[0][0] & " has Address: " & $trxFunctions[0][1] & @CRLF)
    $trxString = DllCallAddress("INT", $trxFunctions[0][1], "BYTE*", $NumberOfTRXunits, "INT", $AvailableTRXunits)
    If @error Then
    switch @error
    Case 2
    ConsoleWrite("unknown ""return type""")

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

    Case 4
    ConsoleWrite("bad number of parameters")

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

    Case 5
    ConsoleWrite("bad parameter")
    EndSwitch
    EndIf

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

    If $handle_trxDLL Then $close_trxDLL = _WinAPI_FreeLibrary($handle_trxDLL)
    ConsoleWrite("$close_trxDLL = " & $close_trxDLL & @CRLF)
    EndFunc

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

    Func InitTRX_02()
    Local $funcReturn = DllCall("trxRemote.dll", "INT", "trxInitialize", "BYTE*", $NumberOfTRXunits, "INT", $AvailableTRXunits)
    If @error Then
    switch @error
    Case 1
    ConsoleWrite("unable to use the DLL file" & @CRLF)

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

    Case 2
    ConsoleWrite("unknown ""return type""" & @CRLF)

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

    Case 3
    ConsoleWrite("""function"" not found in the DLL file" & @CRLF)

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

    Case 4
    ConsoleWrite("bad number of parameters" & @CRLF)

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

    Case 5
    ConsoleWrite("bad parameter" & @CRLF)
    EndSwitch
    EndIf
    EndFunc
    Exit

    [/autoit]
    • Offizieller Beitrag

    Da sowohl NumberOfTRXunits als auch AvailableTRXunits von der Funktion befüllt werden, würde ich die dafür erforderlichen Strukturen erstellen und als Pointer übergeben. Mag sein, dass ein direktes Befüllen auch möglich ist, ich beginne zumindest immer mit der Pointer-Variante.

    [autoit]

    $NumberOfTRXunits = DllStructCreate("byte")
    $pNumberOfTRXunits = DllStructGetPtr($NumberOfTRXunits)

    [/autoit]


    "AvailableTRXunits" erwartet ein Integer-Array "TtrxUnits= Array[0..255] of Integer;". Das ist letztendlich nichts anderes als aneinandergereihter Speicherplatz.

    [autoit]

    $AvailableTRXunits= DllStructCreate("int[256]")
    $pAvailableTRXunits = DllStructGetPtr($AvailableTRXunits)

    [/autoit]


    Sollte die Übergabe des array in der Form nicht funktionieren, kann man auch probieren dieses als Bytearray zu übergeben:

    [autoit]

    $AvailableTRXunits= DllStructCreate("byte[" & 4*256 & "]") ; Integer hat 4 Byte
    $pAvailableTRXunits = DllStructGetPtr($AvailableTRXunits)

    [/autoit]


    Dein Aufruf würde also so aussehen:

    [autoit]

    $aReturn = DllCall("trxRemote.dll", "INT", "trxInitialize", "PTR", $pNumberOfTRXunits, "PTR", $pAvailableTRXunits)

    [/autoit]
  • Hallo BugFix,

    ich kann nur sagen - Danke, Danke, Danke !!!! :rock:
    Es hat sofort funktioniert. Das war ein tolles Weihnachtsgeschenk.
    In diesem Sinne wünsche ich dir ein ebensolches und einen guten Rutsch ins neue Jahr.
    Das hat mir wirklich sehr geholfen. Nochmals Danke.

    Gruß, PixelStorm

  • Hallo Bugfix,

    ich wende mich mal direkt an dich weil ich noch ein einziges Problem mit dieser DLL habe.
    Bis auf eine Funktion habe ich alles zum laufen bekommen, aber diese eine Funktion treibt mich gerade in den Wahnsinn.

    Code
    Das ist ein Ausschnitt aus einer Datei, die mir mit der dll geliefert wurde (trxRemoteIntf.pas)
    Function trxLoadRDS( UnitNr   : Byte;
                         Filename : trxString) : Byte;        stdcall;external 'trxRemote.dll';
    //  This function clears the entire RDS data set and reloads it with data from the given file.
    // The file must be of type .txt_hex

    Und hier ist mein dazugehöriger AutoIt Code

    [autoit]


    Func TX_LoadRDS($Unit, $FileName)
    Global $RDS_String = ""
    Local $i, $x, $RDSStringArray = 0
    $RDSStringArray = StringToASCIIArray($FileName)
    Global $RDSFile = DllStructCreate("BYTE[" & UBound($RDSStringArray) & "]")
    Global $pRDSFile = DllStructGetPtr($RDSFile)
    DllStructSetData ($RDSFile, 1, UBound($RDSStringArray), 1)
    For $i = 1 To UBound($RDSStringArray)
    DllStructSetData ($RDSFile, 1, $RDSStringArray[$x], $i)
    $x += 1
    Next
    $trxString = DllCallAddress("INT", $trxLoadRDS, "BYTE", $Unit, "PTR", $pRDSFile)
    EndFunc

    [/autoit]

    Das Problem: Das File wird nicht geladen sondern AutoIt beendet sich mit: AutoIT3.exe ended.rc:-1073741819

    Ich habe verschiedenes probiert, bekomme es aber einfach nicht hin. Vielleicht hättest du, oder selbstverständlich auch jeder andere, eine Lösung dafür.
    Vielen Dank im Voraus für deine (eure) Hilfe

    Gruß, PixelStorm

  • Hi,

    // The file must be of type .txt_hex


    was bedeutet das "hex"?

    IdR werden Strings einfach so übergeben:

    [autoit]

    $trxString = DllCallAddress("INT", $trxLoadRDS, "BYTE", $Unit, "STR*", $filename)

    [/autoit]


    Das Sternchen in STR* weist an, dass der Pointer auf den String übergeben wird. Testweise lass das Sternchen weg! Falls Unicodestrings verlangt werden, nimm WSTR.
    Alle anderen Zeilen darüber kannst du dir dann sparen!

    Wenn das HEX in .txt_hex etwas zu bedeuten hat, dann könntest du den Filenamen entweder per $hex=stringtobinary($filename) entsprechend umformen, wenn das 0x am Anfang stört, schneide es per stringtrimleft($hex,2) ab.

    //edit
    Es gibt auch die Möglichkeit, dass der Pointer auf einen Pointer auf den String übergeben werden muss! Dann musst du den String in eine CHAR-Struct packen, deren Pointer in ein DWORD und diesen Pointer dann übergeben.
    Oder mit "PTR*",$dllstructgetptr($CHARstruct)

    Was generell immer sinnvoll ist, ist der komplette Sourcecode der Funktion, nicht nur der Header!

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (8. Januar 2015 um 18:44)

  • Hallo Andy,

    vielen Dank erstmal für deine Antwort.

    was bedeutet das "hex"?


    Um es ein wenig transparenter für dich zu machen will ich dir kurz erklären worum es geht.
    Ich habe hier eine Hardware die man mit Hilfe einer dazugehörigen dll programmtechnisch steuern kann.
    In diesem Fall geht es darum das man verschiedene Setups in einer Datei speichern kann, mit der Endung ".txt_hex".
    Diese Datei gibt es und wird auch von der Hardware korrekt eingelesen, wenn ich es manuell mache. Ich will es aber natürlich per AutoIt Script mit der dazugehörigen Funktion aus der dll machen.

    Was generell immer sinnvoll ist, ist der komplette Sourcecode der Funktion, nicht nur der Header!


    Ich habe nur diesen Header. Die eigentliche Funktion befindet sich in der dll. Somit habe ich auch keinen Sourcecode der Funktion.

    Deine Lösungsvorschläge habe ich alle ausprobiert, leider ohne Erfolg. Mir ist einfach nicht klar was an den Übergabeparametern für diese Funktion anders ist als für alle anderen Funktionen in der dll.
    Diese habe ich ja mit Hilfe von BugFix zum laufen bekommen (und sie funktionieren eigentlich alle nach dem gleichen Schema. Nur diese eine Funktion verweigert sich mir :(
    Ich werde mal den kompletten Inhalt der Datei, die mir mit der dll geliefert wurde (trxRemoteIntf.pas) hier einfügen.

    Gruß, PixelStorm

  • Hi,
    ok, der komplette Quellcode hat geholfen.
    So wie es aussieht, wird der Pointer auf den String verlangt, wie bei den anderen Funktionen auch.
    Das "hex" in ".txt_hex" hat demnach weniger mit der Übergabe an die Funktion, sondern eher mit dem Dateiinhalt zu tun...
    Hast du den mal verifiziert?
    Funktionieren die Funktionen trxPS und trxEON_PS?

  • Hallo Andy,

    wie bereits geschrieben, funktionieren alle anderen Funktionen. Habe das hier gerade am laufen und meinem Chef vorgeführt. Nur diese eine Funktion bekomme ich nicht gebacken.
    Und gerade diese würde ich jetzt dringend brauchen :(

    Gruß, PixelStorm

  • Hi,
    wenn die Funktionen trxPS und trxEON_PS funktionieren, dann ist auch deine Übergabe in Ordnung.
    Also könnte es direkt der Datei liegen. Hast du eine Referenzdatei die fehlerfrei arbeitet? Ggf. auch von einem anderen User. Das verwendete Dateiformat wäre dann natürlich auch noch hilfreich.
    Liegt die dll im Scriptverzeichnis?
    Hast du getestet, ob ggf. nur der Dateiname, ohne den Pfad bzw. der komplette Dateipfad verwendet wird?

  • Hallo Andy,

    wie schon in Post #7 geschrieben habe ich eine Referenzdatei, die auch einwandfrei eingelesen wird.
    Die dll liegt im Scriptverzeichnis, warum fragst du? Die wird ja geladen und die anderen Funktionen gehen ja auch.
    Das einzige was ich noch ausprobieren kann ist, die Datei ins Scriptverzeichnis zu legen und versuchen sie ohne Dateipfad zu laden.
    Kann ich aber erst am Montag machen. Ich melde mich nochmals mit dem Ergebnis.
    Schönen Sonntag noch.


    Gruß, PixelStorm

    2 Mal editiert, zuletzt von PixelStorm (12. Januar 2015 um 14:15)

  • Nachtrag zu Post #11:
    Ich habe jetzt mal die Datei direkt in das Scriptverzeichnis gelegt und versucht von dort zu laden, leider auch ohne Erfolg.
    Jetzt bin ich dann wirklich am Ende mit meinen Möglichkeiten.

    Gruß, PixelStorm

  • zeig mal bitte den AutoIt-Code der Funktionen
    trxPS
    trxEON_PS
    trxLoadRDS

    ggf. ist es nur ein typo...

  • Hi Andy,

    anbei mal mein AutoIt Code. Für die Funktionen trxPS und trxEON_PS gibt es jeweils eine Get- und eine Set- Variante. Ich habe dir mal von beiden die Set-Variante gepostet.
    Aber wie bereits gesagt, die Funktionen trxPS und trxEON_PS funktionieren.
    Danke nochmals für deine Mühe :)

    Gruß, PixelStorm

    [autoit]


    #Region TRX011 Constants and Variables ----------------------------------------------------------------------------------------------
    Global Const $TRX01 = 1
    Global Const $TRX02 = 2
    Global $PS_String = ""
    Global $PSCode = DllStructCreate("BYTE[9]")
    Global $pPSCode = DllStructGetPtr($PSCode)
    Global $EONPS_String = ""
    Global $EONPSCode = DllStructCreate("BYTE[9]")
    Global $pEONPSCode = DllStructGetPtr($EONPSCode)
    Global $RDSFile = @WorkingDir & "\Stream.txt_hex"
    #EndRegion TRX011 Constants and Variables -------------------------------------------------------------------------------------------

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

    #Region Function Test() -----------------------------------------------------------------------------------------------------------------
    Func Test()
    Set_TX_PSCode($TRX01, "TRX-01") ; ($Unit, $PSCodeValue = String with a maximum length of 8 characters)
    Set_TX_EONPSCode($TRX01, 0xAAAA, "TRX-02") ; ($Unit, $PI_CODE = 0x0000 to 0xFFFF, $EONPSCodeValue = String with a maximum length of 8 characters)
    TX_LoadRDS($TRX02, $RDSFile)
    EndFunc
    #EndRegion Function Test() --------------------------------------------------------------------------------------------------------------

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

    #Region Function Set_TX_PSCode() --------------------------------------------------------------------------------------------------------
    #cs #####################################################################################################################################
    # Function: Set_TX_PSCode($Unit, $PSCodeValue) #
    #ce #####################################################################################################################################
    Func Set_TX_PSCode($Unit, $PSCodeValue)
    Local $i, $x, $PSStringArray = 0
    If StringLen($PSCodeValue) > 8 Then
    MsgBox(BitOR($MB_SYSTEMMODAL, $MB_ICONWARNING), "Error setting the PS-String!!!", "The given PS-String has " & StringLen($PSCodeValue) & " characters." & @CRLF _
    & "The string will be truncated to 8 characters !!!")
    $PSCodeValue = StringTrimRight($PSCodeValue, StringLen($PSCodeValue) - 8)
    EndIf
    $PSStringArray = StringToASCIIArray($PSCodeValue)
    DllStructSetData ($PSCode, 1, UBound($PSStringArray), 1)
    For $i = 2 To UBound($PSStringArray) + 1
    DllStructSetData ($PSCode, 1, $PSStringArray[$x], $i)
    $x += 1
    Next
    $trxString = DllCallAddress("INT", $trxPS, "BYTE", $Unit, "BOOLEAN", True, "PTR", $pPSCode)
    EndFunc
    #EndRegion Function Set_TX_PSCode() -----------------------------------------------------------------------------------------------------

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

    #Region Function Set_TX_EONPSCode() -----------------------------------------------------------------------------------------------------
    #cs #####################################################################################################################################
    # Function: Set_TX_EONPSCode($Unit, $PI_CODE, $EONPSCodeValue) #
    #ce #####################################################################################################################################
    Func Set_TX_EONPSCode($Unit, $PI_CODE, $EONPSCodeValue)
    Local $i, $x, $EONPSStringArray = 0
    If StringLen($EONPSCodeValue) > 8 Then
    MsgBox(BitOR($MB_SYSTEMMODAL, $MB_ICONWARNING), "Error setting the PS-String!!!", "The given EONPS-String has " & StringLen($EONPSCodeValue) & " characters." & @CRLF _
    & "The string will be truncated to 8 characters !!!")
    $EONPSCodeValue = StringTrimRight($EONPSCodeValue, StringLen($EONPSCodeValue) - 8)
    EndIf
    $EONPSStringArray = StringToASCIIArray($EONPSCodeValue)
    DllStructSetData ($EONPSCode, 1, UBound($EONPSStringArray), 1)
    For $i = 2 To UBound($EONPSStringArray) + 1
    DllStructSetData ($EONPSCode, 1, $EONPSStringArray[$x], $i)
    $x += 1
    Next
    $trxString = DllCallAddress("INT", $trxEON_PS, "BYTE", $Unit, "BOOLEAN", True, "INT", $PI_CODE, "PTR", $pEONPSCode)
    EndFunc
    #EndRegion Function Set_TX_EONPSCode() --------------------------------------------------------------------------------------------------
    #Region Function TX_LoadRDS() -----------------------------------------------------------------------------------------------------------
    #cs #####################################################################################################################################
    # Function: TX_LoadRDS($Unit, $FileName) #
    #ce #####################################################################################################################################
    Func TX_LoadRDS($Unit, $FileName)
    ;DllCallAddress ( "return type", address [, type1, param1 [, type n, param n]] )
    $trxString = DllCallAddress("INT", $trxLoadRDS, "BYTE", $Unit, "STR", $FileName)
    ; Ich habe auch diese Variante probiert:
    ;$trxString = DllCallAddress("INT", $trxLoadRDS, "BYTE", $Unit, "STR*", $FileName)
    ;Ebenfalls ohne Erfolg
    EndFunc
    #EndRegion Function TX_LoadRDS() --------------------------------------------------------------------------------------------------------

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