Probleme mit DllCall

  • Hallo zusammen,
    habe da ein Problem, ich möchte mein DMX - Interface mit Autoit und einer DLL steuern. Die dll hänge ich mal an. Die Referenz findet man unter: http://www.pcdmx.de/ger/hardware/usbdmx1/dllinfo.htm
    Hier mein Code

    [autoit]

    $hDll = DllOpen("DasHard.dll")
    ConsoleWrite( DllCall($hDll,"int","DasHardCommand","int",1,"int",1,"str","")& @error &@CRLF)
    DllClose($hDll)

    [/autoit]


    Das Problem ist, dass ich mir nicht sicher bin, ob der DllCall so richtig ist, da ich noch nie mit Dlls gearbeitet habe^^
    So wie der Code jetzt ist beendet sich Autoit schon bevor überhaupt irgendetwas in die Konsole geschrieben wird.
    greetz DJ

    Einmal editiert, zuletzt von DjBasslord (6. November 2008 um 17:45)

  • Name der Funktion in der Dll ist: _DasHardCommand@12 (steht bei Alias vom VB-Code :) )
    und statt "str","" solltest du folgendes verwenden:
    "ptr",0
    oder

    [autoit]

    $dmxparam = DllstructCreate("byte[" & $length & "]")
    "ptr",DllstructGetptr($dmxparam)

    [/autoit]


    Je nachdem, ob Der Parameter verwendet wird, oder nicht :)

  • Hey Progandy, danke dir jetzt stürtzt Autoit schonmal nicht mehr ab, aber leider bekomme ich beim DllCall einen Error von 3, d.H. dass die FUnktion nicht gefunden wurde...

    Einmal editiert, zuletzt von DjBasslord (6. November 2008 um 17:43)

  • Seit wann braucht AutoIt den VB-Alias? Allerdings brauchst du für den letzten Parameter einen "ubyte*" als Typ. (char bei C** ist byte bei AutoIt. Wieso char nicht byte heißt (in C++) hab ich mich auch schon gefragt.)

    Projekte: Keine größeren (und fertigen)
    Gegen Internetzensur:
    https://epetitionen.bundestag.de/index.php?acti…s;petition=3860
    (Zeichnungsfrist abgelaufen)
    __________________________________________________________________________________________________________________________________
    Dieser Beitrag wurde bereits 264 mal editiert, zuletzt von »Fast2« (30. Februar 2009, 12:99)

  • Moin,

    Name der Funktion in der Dll ist: _DasHardCommand@12 (steht bei Alias vom VB-Code :) )

    Das ist die Compiler-Signatur der Funktion. ;)
    http://de.wikipedia.org/wiki/Signatur_(Programmierung)

    Zitat von Mario2323

    apropo parameter. wie findet man parameter bei einer dll raus?

    Nun, entweder sind sie dokumentiert oder es sieht schlecht aus.
    Mit Dependency Walker kann man einiges in Erfahrung bringen, aber das genügt meist nicht ...

    EDIT:
    In den Beispielen heißt die Funktion komischerweise anders, vielleicht ist das der Fehler ...

    Ich habe dir mal die Beispiele übersetzt, aber nicht getestet ...

    Spoiler anzeigen
    [autoit]


    ; Konstanten

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

    Global Const $DHC_SIUDI0 = 0 ; COMMAND
    Global Const $DHC_SIUDI1 = 100 ; COMMAND
    Global Const $DHC_SIUDI2 = 200 ; COMMAND
    Global Const $DHC_SIUDI3 = 300 ; COMMAND
    Global Const $DHC_SIUDI4 = 400 ; COMMAND
    Global Const $DHC_SIUDI5 = 500 ; COMMAND
    Global Const $DHC_SIUDI6 = 600 ; COMMAND
    Global Const $DHC_SIUDI7 = 700 ; COMMAND
    Global Const $DHC_SIUDI8 = 800 ; COMMAND
    Global Const $DHC_SIUDI9 = 900 ; COMMAND

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

    Global Const $DHC_OPEN = 1 ; COMMAND
    Global Const $DHC_CLOSE = 2 ; COMMAND
    Global Const $DHC_DMXOUTOFF = 3 ; COMMAND
    Global Const $DHC_DMXOUT = 4 ; COMMAND
    Global Const $DHC_PORTREAD = 5 ; COMMAND
    Global Const $DHC_PORTCONFIG = 6 ; COMMAND
    Global Const $DHC_VERSION = 7 ; COMMAND
    Global Const $DHC_DMXIN = 8 ; COMMAND

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

    Global Const $DHC_RESET = 11 ; COMMAND
    Global Const $DHC_DEBUG_OPEN = 12 ; COMMAND
    Global Const $DHC_DEBUG_CLOSE = 13 ; COMMAND

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

    Global Const $DHC_WRITEMEMORY = 21 ; COMMAND
    Global Const $DHC_READMEMORY = 22 ; COMMAND
    Global Const $DHC_SIZEMEMORY = 23 ; COMMAND

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

    Global Const $DHC_3DWRITE = 25 ; COMMAND
    Global Const $DHC_3DREAD = 26 ; COMMAND
    Global Const $DHC_MMWRITE = 27 ; COMMAND
    Global Const $DHC_MMREAD = 28 ; COMMAND

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

    Global Const $DHC_TRANSPORT = 30 ; COMMAND
    Global Const $DHP_TRANSPORT_MODEALW = 1 ; PARAM
    Global Const $DHP_TRANSPORT_MODEALW32 = 2 ; PARAM
    Global Const $DHP_TRANSPORT_MODEOPT = 3 ; PARAM DEFAULT
    Global Const $DHP_TRANSPORT_MODEOPT32 = 4 ; PARAM

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

    Global Const $DHC_SERIALNREAD = 47 ; COMMAND
    Global Const $DHC_SERIALNWRITE = 48 ; COMMAND

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

    Global Const $DHE_OK = 1 ; RETURN NO ERROR
    Global Const $DHE_NOTHINGTODO = 2 ; RETURN NO ERROR

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

    Global Const $DHE_ERROR_COMMAND = -1 ; RETURN ERROR
    Global Const $DHE_ERROR_NOTOPEN = -2 ; RETURN ERROR
    Global Const $DHE_DMXOUT_PACKWRITE = -1000 ; RETURN ERROR -1005 = ERROR_ACCESS_DENIED -1023 = ERROR_CRC
    Global Const $DHE_DMXOUT_PACKREAD = -1100 ; RETURN ERROR

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

    ; Dll öffnen
    Global Const $dhcDll = DllOpen ('DasHard.dll')

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

    Opt ('OnExitFunc', 'Terminate')

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

    ; Dll schließen
    Func Teminate ( )

    DllClose ('DasHard.dll')

    EndFunc

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

    ; *** Dll Funktion ***
    Func HardDllCommand ($iCommand, $iParam, $pBloc)

    $aRes = DllCall ($dhcDll, 'int', 'HardDllCommand', _
    'int', $iCommand, _
    'int', $iParam, _
    'uchar*', $pBloc)
    Return $aRes[0]

    EndFunc

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

    ; *** Open the interface when your application start :

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

    Dim $v, $interface_open; // global
    $dmxblock = DllStructCreate ('uchar dmxblock[512]'); // global

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

    $interface_open = HardDllCommand ($DHC_OPEN,0,0);
    if ($interface_open > 0) then
    for $i = 1 to 512
    DllStructSetData ($dmxblock, 'dmxblock', 0, $i);
    $v = HardDllCommand ($DHC_DMXOUTOFF,0,0);
    next
    endif
    ; Note :
    ; - When you open the interface, you don't know the state of the DMX output levels
    ; into the interface. It's why it's better to clean all DMX levels to be sure.

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

    ; *** Send the DMX and read the PORT everytime :

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

    Dim $v, $ports;
    if ($interface_open > 0) then
    $ports = HardDllCommand ($DHC_PORTREAD,0,0);
    $v = HardDllCommand ($DHC_DMXOUT, 512, DllStructGetPtr ($dmxblock, 'dmxblock')); evtl. 'dmxblock[0]' ...
    if ($v < 0) then
    $v = HardDllCommand ($DHC_CLOSE,0,0);
    $v = HardDllCommand ($DHC_OPEN,0,0);
    endif
    endif

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

    ; Note :
    ; - When you use the DHC_DMXOUT command, the DLL analyses your DMX block.
    ; If there is no changes on the DMX levels, the function returns DHE_NOTHINGTODO and
    ; the DLL don't make a USB communication to save the CPU time of your computer.
    ; - After 6 seconds without USB communication, the USBDMX1 and interfaces go in stand alone mode
    ; (it's a nice feature, if the computer fails). It's why we propose to read the state of the
    ; port everytime to force a USB communication, with this, the interface do not go in stand alone mode.
    ; - If the DHC_DMXOUT command fails (for example, if the user unplug the USB interface !), you need
    ; to close and try to open again the interface.

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

    ; *** Close the interface when your application finish :

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

    Dim $v;
    if ($interface_open>0) then _
    $v = HardDllCommand ($DHC_CLOSE,0,0);

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

    EDIT 2:
    Ich habe mit Dependency Walker nachgesehen, der Name der Funktion ist HardDllCommand.


    LG
    Greenhorn


    3 Mal editiert, zuletzt von Greenhorn (10. November 2008 um 15:44)

  • mit dependency walker bekommt man den echten Funktionsnamen heraus... in der geposteten DLL ist das "DasHardCommand". Das sollte echt mal auf der Seite angepasst werden. Da findet man 3 oder 4 verschiedenen Namen ...
    Greenhorn: ich hab die DLL aus post #1 von diesem Thread genommen, du wohl die von der HP?

  • Greenhorn: ich hab die DLL aus post #1 von diesem Thread genommen, du wohl die von der HP?


    Hast natürlich Recht, es ist DasHardCommand, jetzt komme ich ganz und gar durcheinander ... :D

    Also, bitte die Funktion umbenennen !

    [autoit]


    ; *** Dll Funktion ***
    Func HardDllCommand ($iCommand, $iParam, $pBloc)

    $aRes = DllCall ($dhcDll, 'int', 'DasHardCommand', _
    'int', $iCommand, _
    'int', $iParam, _
    'uchar*', $pBloc)
    Return $aRes[0]

    EndFunc

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

    Pause ...

    LG
    Greenhorn


  • THx schonmal an alle die sich hier beteiligt haben.
    @ Greenhorn, danke für deine Übersetzung, sind zwar ein paar kleine Fehler drine aber die bekomme ich schon behoben.
    Das mit dem unsigenedcharpointer tuts ja nicht in Autoit bei nem DLLCall, muss ich dann unsignedbytepointer nehmen sollte ja so ziemlich das selbe sein?
    Ich denke nämlich, dass es an dem Letzten Parameter immer scheitert ....
    greetz DJ

    Einmal editiert, zuletzt von DjBasslord (10. November 2008 um 16:35)

  • Müsste so sen, mit ptr als Parameter

    Spoiler anzeigen
    [autoit]

    ; *** Dll Funktion ***
    Func HardDllCommand ($iCommand, $iParam, $pBloc)

    $aRes = DllCall ($dhcDll, 'int', 'DasHardCommand', _
    'int', $iCommand, _
    'int', $iParam, _
    'ptr', $pBloc)
    Return $aRes[0]

    EndFunc
    $DHC_DMXOUTOFF = 3
    $DHC_OPEN = 1
    $dmxdata = DllStructCreate("ubyte[512]")

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

    ; ohne dmxdata
    HardDllCommand ($DHC_OPEN, 11, 0)
    ; Mit dmxdata
    HardDllCommand ($DHC_DMXOUTOFF, 512, DllstructGetPtr($dmxdata))
    ...

    [/autoit]
  • Ja, hast Recht. char, bzw. uchar gibt's nur in DllStructCreate() ...

    Dann nimm ubyte*, der Datentyp BYTE ist Microsoft Schnick-Schnack für char ...
    MWL.zip

    [autoit]

    ; *** Dll Funktion ***
    Func HardDllCommand ($iCommand, $iParam, $pBloc)

    $aRes = DllCall ($dhcDll, 'int', 'DasHardCommand', _
    'int', $iCommand, _
    'int', $iParam, _
    'ubyte*', $pBloc)
    Return $aRes[0]

    EndFunc

    [/autoit]

    EDIT:
    ProgAndy's variante könnte ebenso klappen, musst Du mal durchtesten ...

    LG
    Greenhorn


    2 Mal editiert, zuletzt von Greenhorn (10. November 2008 um 17:04)

  • Hm das ist alles Käse mit der dämlichen Dll und Autoit, dass tuts vorne und hinten nicht -.-, bei uchar* gibt der DLLCall en Fehler wieder, und bei ubyte* hängt sich Autoit ganz auf und beendet sich :cursing:
    PS: das mit ptr funktioniert leider auch nicht, es wird immer "!>16:56:25 AutoIT3.exe ended.rc:-1073741819" in der Konsole ausgegeben...

  • :( Hab nochmal das ganze Bsp-Skript so aufgebaut, wie es meiner Meinung nach sein solte :)

    Spoiler anzeigen
    [autoit]

    ; Greenhorn, Prog@ndy
    Global Const $DHC_SIUDI0 = 0 ; COMMAND
    Global Const $DHC_SIUDI1 = 100 ; COMMAND
    Global Const $DHC_SIUDI2 = 200 ; COMMAND
    Global Const $DHC_SIUDI3 = 300 ; COMMAND
    Global Const $DHC_SIUDI4 = 400 ; COMMAND
    Global Const $DHC_SIUDI5 = 500 ; COMMAND
    Global Const $DHC_SIUDI6 = 600 ; COMMAND
    Global Const $DHC_SIUDI7 = 700 ; COMMAND
    Global Const $DHC_SIUDI8 = 800 ; COMMAND
    Global Const $DHC_SIUDI9 = 900 ; COMMAND

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

    Global Const $DHC_OPEN = 1 ; COMMAND
    Global Const $DHC_CLOSE = 2 ; COMMAND
    Global Const $DHC_DMXOUTOFF = 3 ; COMMAND
    Global Const $DHC_DMXOUT = 4 ; COMMAND
    Global Const $DHC_PORTREAD = 5 ; COMMAND
    Global Const $DHC_PORTCONFIG = 6 ; COMMAND
    Global Const $DHC_VERSION = 7 ; COMMAND
    Global Const $DHC_DMXIN = 8 ; COMMAND

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

    Global Const $DHC_RESET = 11 ; COMMAND
    Global Const $DHC_DEBUG_OPEN = 12 ; COMMAND
    Global Const $DHC_DEBUG_CLOSE = 13 ; COMMAND

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

    Global Const $DHC_WRITEMEMORY = 21 ; COMMAND
    Global Const $DHC_READMEMORY = 22 ; COMMAND
    Global Const $DHC_SIZEMEMORY = 23 ; COMMAND

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

    Global Const $DHC_3DWRITE = 25 ; COMMAND
    Global Const $DHC_3DREAD = 26 ; COMMAND
    Global Const $DHC_MMWRITE = 27 ; COMMAND
    Global Const $DHC_MMREAD = 28 ; COMMAND

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

    Global Const $DHC_TRANSPORT = 30 ; COMMAND
    Global Const $DHP_TRANSPORT_MODEALW = 1 ; PARAM
    Global Const $DHP_TRANSPORT_MODEALW32 = 2 ; PARAM
    Global Const $DHP_TRANSPORT_MODEOPT = 3 ; PARAM DEFAULT
    Global Const $DHP_TRANSPORT_MODEOPT32 = 4 ; PARAM

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

    Global Const $DHC_SERIALNREAD = 47 ; COMMAND
    Global Const $DHC_SERIALNWRITE = 48 ; COMMAND

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

    Global Const $DHE_OK = 1 ; RETURN NO ERROR
    Global Const $DHE_NOTHINGTODO = 2 ; RETURN NO ERROR

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

    Global Const $DHE_ERROR_COMMAND = -1 ; RETURN ERROR
    Global Const $DHE_ERROR_NOTOPEN = -2 ; RETURN ERROR
    Global Const $DHE_DMXOUT_PACKWRITE = -1000 ; RETURN ERROR -1005 = ERROR_ACCESS_DENIED -1023 = ERROR_CRC
    Global Const $DHE_DMXOUT_PACKREAD = -1100 ; RETURN ERROR

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

    ; Dll öffnen
    Global Const $dhcDll = DllOpen ('DasHard.dll')

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

    ; *** Dll Funktion ***
    Func HardDllCommand ($iCommand, $iParam, $pBloc)

    $aRes = DllCall ($dhcDll, 'int', 'DasHardCommand', _
    'int', $iCommand, _
    'int', $iParam, _
    'ptr', $pBloc)
    Return $aRes[0]

    EndFunc

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

    ; *** Open the interface when your application start :

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

    Dim $v, $interface_open; // global
    $dmxblock = DllStructCreate ('byte[512]'); // global

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

    $interface_open = HardDllCommand ($DHC_OPEN,0,0);
    if ($interface_open > 0) then
    ; Das 0-setzen wird hier nicht benötigt :)
    ;~ for $i = 1 to 512
    ;~ DllStructSetData ($dmxblock, 1, 0, $i);
    ;~ next
    $v = HardDllCommand ($DHC_DMXOUTOFF,0,0);
    endif
    ; Note :
    ; - When you open the interface, you don't know the state of the DMX output levels
    ; into the interface. It's why it's better to clean all DMX levels to be sure.

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

    ; *** Send the DMX and read the PORT everytime :

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

    Dim $v, $ports;
    if ($interface_open > 0) then
    $ports = HardDllCommand ($DHC_PORTREAD,0,0);
    $v = HardDllCommand ($DHC_DMXOUT, 512, DllStructGetPtr ($dmxblock)); evtl. 'dmxblock[0]' ...
    if ($v < 0) then
    $v = HardDllCommand ($DHC_CLOSE,0,0);
    $v = HardDllCommand ($DHC_OPEN,0,0);
    endif
    endif

    ; Die DMX-Daten müssten da sein.

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

    ; Note :
    ; - When you use the DHC_DMXOUT command, the DLL analyses your DMX block.
    ; If there is no changes on the DMX levels, the function returns DHE_NOTHINGTODO and
    ; the DLL don't make a USB communication to save the CPU time of your computer.
    ; - After 6 seconds without USB communication, the USBDMX1 and interfaces go in stand alone mode
    ; (it's a nice feature, if the computer fails). It's why we propose to read the state of the
    ; port everytime to force a USB communication, with this, the interface do not go in stand alone mode.
    ; - If the DHC_DMXOUT command fails (for example, if the user unplug the USB interface !), you need
    ; to close and try to open again the interface.

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

    ; *** Close the interface when your application finish :

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

    Dim $v;
    if ($interface_open>0) then _
    $v = HardDllCommand ($DHC_CLOSE,0,0);

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit]
  • OK, Forensik. :D

    Poste doch bitte mal dein Testskript und erkläre was für Daten in dem Block übertragen werden sollen, vielleicht kommen wir dann weiter ...


    LG
    Greenhorn

    p.s.: Das Szenario kommt mir bekannt vor ..., irgendwie ... :D

    Zitat von DjBasslord

    Hm das ist alles Käse mit der dämlichen Dll und Autoit, dass tuts vorne und hinten nicht -.-, bei uchar* gibt der DLLCall en Fehler wieder, und bei ubyte* hängt sich Autoit ganz auf und beendet sich :cursing:
    PS: das mit ptr funktioniert leider auch nicht, es wird immer "!>16:56:25 AutoIT3.exe ended.rc:-1073741819" in der Konsole ausgegeben...


    Einmal editiert, zuletzt von Greenhorn (10. November 2008 um 17:49)

  • Hm das Problem ist leider, dass ich noch nicht mal dazu komme, Daten zu senden, da ich das Interface noch nichtmal per DllCall öffnen kann, da sich Autoit dann verabschiedet -.-. Meine Vermutung liegt nun darin, dass das wohl vllt am Letzten Parameter liegen könnte. Später sollen dann Werte von 0 - 255 zum Interface gesendet werden.
    Ein Testskript habe ich soweit eig garnicht, weil ich von DllCalls überhaupt keine Ahnung habe. Aber ich denke mal, um zutesten ob das funktioiert muss man ja nicht das Interface haben, da die Dll dann 0 zurückliefert wenn das Interface nicht angeschloßen ist.
    Habe außerdem ncoh einwenig ein bisschen rumgesucht und noch ein bssl Code gefunden ==> http://karistouf.free.fr/dmxfreelab.htm
    greetz DJ

  • Hm das Problem ist leider, dass ich noch nicht mal dazu komme, Daten zu senden, da ich das Interface noch nichtmal per DllCall öffnen kann, da sich Autoit dann verabschiedet -.-. Meine Vermutung liegt nun darin, dass das wohl vllt am Letzten Parameter liegen könnte. Später sollen dann Werte von 0 - 255 zum Interface gesendet werden.
    Ein Testskript habe ich soweit eig garnicht, weil ich von DllCalls überhaupt keine Ahnung habe. Aber ich denke mal, um zutesten ob das funktioiert muss man ja nicht das Interface haben, da die Dll dann 0 zurückliefert wenn das Interface nicht angeschloßen ist.
    Habe außerdem ncoh einwenig ein bisschen rumgesucht und noch ein bssl Code gefunden ==> http://karistouf.free.fr/dmxfreelab.htm
    greetz DJ

    0 bis 255, also ein unsigned char !

    Dann muss es damit klappen. Hast Du alle anderen Fehlerquellen ausgeschlossen, manchmal übersieht man das einfachste (ich spreche aus Erfahrung ) ...
    Wird die DLL geladen ?
    Was sind die Rückgabewerte von DllCall, Du hast die DHC_... Errorwerte zum überprüfen.


    LG
    Greenhorn

    p.s. muss kurz in den Topf gucken ... ;)