Jump to content

Shared Memory via Dll


livewire
 Share

Recommended Posts

at now, we can't share a variable (DllStructCreate) between 2 autoit scripts !

maybe, only throw an external dll but not directly between 2 autoit script

There's this way although I think you didn't like it.

Can you say what you want to do and how you expect the transfer to operate?

It adds to the difficulty that I don't how how to get pointers to variables apart from dllstructgetptr. But if there are a few variable which have to be transferred quickly, and some which could be transferred less urgently then you could deal with it by having a different way to read and set these variables.

For the general variables they can be transferred every so many mS using AdlibEnable as in my example, or a timer.

For the urgent ones you could make functions with special variables so you could have

SetShared($var,56) to replace $var = 56, where SetShared sets the value in the DllStruct so that it can be read immediately by the other program, and you could have $xy = GetShared($var) to replace $xy = $var. The other program could do the same so the updates for these special variables could be very fast.

I'm trying to produce some functions for this sort of thing so any input you can give would help.

One problem I have is that because I can't get pointers to variables I can only transfer global variables.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

There's this way although I think you didn't like it.

Can you say what you want to do and how you expect the transfer to operate?

Ok, what i need is: to run 3 instances of the same script.

the script do this:

While 1
    
    If Get($SharedVariable)=="Stop_LOOPING" then Exit; we exit program
        
    $htm=_INetGetSource($url)
    
    If StringInStr($htm,"finish") or Get($SharedVariable)=="Stop_LOOPING" Then 
        Set($SharedVariable,"Stop_LOOPING"); to inform the other instances of the same script
        Exit
    EndIf

WEnd

;Get($SharedVariable) and Set($SharedVariable) are function to read / write the value of $SharedVariable

$SharedVariable act here as a flag indicator between same scripts

Martin, i read your example but it use GUIGetMsg() function that mean x milliseconds for waiting/looping GuiMsg...My project need to be more reactive than GUI application...(sorry for my poor english, but i'm doing all my best...)

Just an other qestion: did you have an exemple for how we can share a DllStruct between scripts without externall dll ?

Thinks again for help and ideas

Edited by mary
Link to comment
Share on other sites

Ok, what i need is: to run 3 instances of the same script.

the script do this:

While 1
    
    If Get($SharedVariable)=="Stop_LOOPING" then Exit; we exit program
        
    $htm=_INetGetSource($url)
    
    If StringInStr($htm,"finish") or Get($SharedVariable)=="Stop_LOOPING" Then 
        Set($SharedVariable,"Stop_LOOPING"); to inform the other instances of the same script
        Exit
    EndIf

WEnd

;Get($SharedVariable) and Set($SharedVariable) are function to read / write the value of $SharedVariable

$SharedVariable act here as a flag indicator between same scripts

Martin, i read your example but it use GUIGetMsg() function that mean x milliseconds for waiting/looping GuiMsg...My project need to be more reactive than GUI application...(sorry for my poor english, but i'm doing all my best...)

Thinks again for help and ideas

I can produce a script to do what you want, but I need to understand a little more. Having 3 instances is fine.

Are all 3 scripts loading the same source from the same url? If so they will all find the 'finish' and stop anyway so the shared variable is not needed. So I assume that all three scripts are reading different urls. Is that correct?

Also, I don't see the need for such fast reactions if you are using _InetGetSorce because that will take more time than the GuiGetMsg() function. Anyway it's not a problem because the data can be written and read as fast as your while loop can go.

I'll wait for your answers before I produce anything, and then it will be a few hours before I have a look at it.

Just an other qestion: did you have an exemple for how we can share a DllStruct between scripts without externall dll ?

my example in the 'data interchange between scripts' thread, post #15, doesn't use an external dll.

I updated the example a few minutes after you posted above.

Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

I can produce a script to do what you want, but I need to understand a little more. Having 3 instances is fine.

Are all 3 scripts loading the same source from the same url? If so they will all find the 'finish' and stop anyway so the shared variable is not needed.

no, it is the same url ! and i load 3 scripts because TCP packets don't take the same route (road), so not the same timediff:

exemple

script1 ==>HTTP packet take 50 millisecond (to get html source)

script2 ==>HTTP packet take 45 milliseconds

script3 ==>HTTP packet take 39 milliseconds

(and for an other loop it maybe differents timediffs for reach call of _inetgetsource)

The html source of url is realtime updating (dynamic page)

my goal is to submit only one form as soon as possible (betting system) at the best time (exactly when html source contain the substring "FINISH").

Edited by mary
Link to comment
Share on other sites

no, it is the same url ! and i load 3 scripts because TCP packets don't take the same route (road), so not the same timediff:

exemple

script1 ==>HTTP packet take 50 millisecond (to get html source)

script2 ==>HTTP packet take 45 milliseconds

script3 ==>HTTP packet take 39 milliseconds

(and for an other loop it maybe differents timediffs for reach call of _inetgetsource)

The html source of url is realtime updating (dynamic page)

my goal is to submit only one form as soon as possible (betting system) at the best time (exactly when html source contain the substring "FINISH").

Here is a script which is very rushed, untidy and uncommented and works I think.

You can run up to 9 instances, after 9 there is some bug which I'm not going to worry about.

The first one to run will set itself up to be the master, the others are slaves.

To test it I have a button "finish" which simulates getting the word "finish" in the text. You can click finish on any of the windows and they will all close.

For your application you need to set the $url which is near the top of the script, and remove the comments in the while loop for the line with _InetGetSource (2 lines).

You need the nomadmemory.au3 file.

Obviously you have to add some code to set the time or whatever you need. I find it difficult to understand why you need to time a change in a web site to milliseconds, or how the information could be used unless it is necessary to react to the word finish before anyone else to get a prize, in which case I hope you will remember me in your will.

#include <guiconstants.au3>
#include <misc.au3>
#include <nomadmemory.au3>

Global $url = "somewhere.com\page1\index.html";<--------------------

Opt("GUIOnEventMode",1)
GUICreate("ms_finisher",250,70)
$labmem = GUICtrlCreateLabel("mem",20,20,120,28)
$ButF = GUICtrlCreateButton("Finish",20,40,120,26)
GUISetState()

GUICtrlSetOnEvent($ButF,"finish")
GUISetOnEvent($GUI_EVENT_CLOSE,"done")
Const $Stop_LOOPING = 1
Const $SharedVariable = 1
Global $instance = True, $inst = 0, $highSlave = 0,$htm = "started"
While $Instance = true
    $inst += 1
    _Singleton("mary_script" & $inst,1)
    $instance = @error = 183
WEnd
WinSetTitle("ms_finisher","","ms_finisher" & $inst)

If $inst = 1 Then
    $master = True;this program is the master
    $d = DllStructCreate("int")
    DllStructSetData($d,1,0);0 = not finished
    $Address = DllStructGetPtr($d)
    GUIRegisterMsg(2001,"tellAddr"); respond to requests for the address to use
    GUICtrlSetData($labmem,Hex($Address))
Else
    $master = False;this program is one of the slaves
;get info on master
    Global $pid = WinGetProcess("ms_finisher1"),$hid = WinGetHandle("ms_finisher1")

    Global $MemOpen = _MemoryOpen($pid), $memadd = 0

    GUIRegisterMsg(2000,"getaddr")
    _SendMessage($hid,2001,$inst);tell master that instance no exists
;master will then send message to us with address to use
EndIf

If $master Then
    While 1
        If DllStructGetData($d,1) = $Stop_LOOPING then MasterExit(); we exit program

;$htm=_INetGetSource($url);<------------------------------------
        

        If StringInStr($htm,"finish") And DllStructGetData($d,1) <> $Stop_LOOPING then
            DllStructSetData($d,$SharedVariable,$Stop_LOOPING); to inform the other instances of the same script
            MasterExit()
        EndIf
    WEnd
Else
    
    While 1

        If Get($SharedVariable) = $Stop_LOOPING then SlaveExit(); we exit program

;$htm=_INetGetSource($url);<----------------------------------------

        If StringInStr($htm,"finish") And Get($SharedVariable) <> $Stop_LOOPING Then
            Set($SharedVariable,$Stop_LOOPING); to inform the other instances of the same script
            SlaveExit()
        EndIf

    WEnd
EndIf

Func Finish()
    $htm = 'will finish this now'
;ConsoleWrite("finishing" & @CRLF)
EndFunc

Func Get($var)
;only reads one int in this script so $var ignored
    Return _MemoryRead($memadd, $MemOpen, "int")
    
EndFunc

Func Set($var,$val)
;only write one int in this script so $var ignored
    _MemoryWrite($memadd, $MemOpen, $val,"int")
EndFunc

Func Done()
    Exit
EndFunc



Func tellAddr($hWndGUI, $MsgID, $WParam, $LParam)
    If $MsgID = 2001 Then
        $Sn = Number($Wparam)
        $titlen = "ms_finisher" & $Sn
;If $Sn = 10 Then MsgBox(0,"TEN",$titlen)
        _SendMessage(WinGetHandle($titlen), 2000, $Address)
        If $sn > $highSlave Then $HighSlave = $Sn
    EndIf
    
EndFunc


Func getaddr($hWndGUI, $MsgID, $WParam, $LParam)
    If $MsgID = 2000 Then
        $memadd = $WParam
        GUICtrlSetData($labmem,Hex($WParam))
;MsgBox(0,"mem = ", Hex($Wparam))
    EndIf
    
EndFunc;==>getaddr

Func SlaveExit()
;MsgBox(0,"SLAVE EXIT",$inst)
    _MemoryClose($MemOpen)
    Exit
    
EndFunc


Func MasterExit()
;wait For all slaves To die
    
    For $nn = 2 To $highSlave
        $Instance = True
        $inst = $nn
        While $Instance = true
            _Singleton("mary_script" & $nn,1)
            $instance = @error = 183
        WEnd
    Next
    $d = 0;kill struct
    Exit
EndFunc

EDIT:spelling

Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

thinks martin !

i'm testing your code and it work .

so, your technique is to store shared variable in a master GUi component and use windows message to read/write ?

Not quite.

The technique is

One script has to be the master. The one I did for you is a bit special because it can decide whether to be a master or a slave which I did because you wanted identical scripts.

When a script is run it looks to see if any others are running. If not it becomes the master. If there are others running then it finds out how many and becomes slave number X, where X is is the first number it finds is not used.

The master creates a struct with dllstructcreate. It gets the address of the struct with DllStriuctGetPtr.

The slaves need to read this struct and have to know the memory address.

In the script for you the master doesn't know how many slaves there are, or when they might be created. So when a slave is created, it works out what number it should be and sends a message to the master giving its id number. The first slave is number 2 next is number 3. Then when the master gets this message it sends a reply telling the slave the memory address to use. This way an extra slave can be created at any time and join in. After 9 it doesn't work and I can't see why not.

Apologies that the program is a mess and there are no comments.

The master just writes to or reads the Dllstruct.

The slaves read the memory, or writes to the memory using the functions in the nomadmemory udf, and based on the memory address given by the master.

The messages are only sent once to each new slave. You could kill slave 5 say, then run another instance of the script and it will become slave 5 again, send a message to the master, get a reply and then it's ready.

I hope all this makes sense.

I have tried various ways to get a slave to create a struct at the same address so that the memory udf is not needed but it always fails. Something is lacking in my understanding somewhere.

Glad it worked. Always a bit of a surprise isn't it?

Sorry to be picky, but when you say thinks do you mean thanks?

EDIT: Apologies liverwire. This is your thread and we've gone a bit off subject, this should have been somewhere else.

Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

ah ! sorry i mean Thanks (not thinks :)

ok, now i understand .

I like your idea (master send adress of a shared variable to slaves) ! I did have a similar idea but without udf memory :

script1 create a dllstruc, get it adress and run(scriptx.exe adress_of_dllstruc), script3....i.e using adress of dllstruct as a commandline parameter. But it did not work...

Thanks again for your great help and pedagogy !!!

Edited by mary
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...