Sign in to follow this  
Followers 0
manni

Problem with DllStructCreate

13 posts in this topic

Hi all,

I'm having problems with DllStructCreate:

When running the following script, it enters an infinite loop, because DllStructCreate returns

always the same memory address (obtained with DllStructGetPtr() )

#include <Array.au3>

Global $Cmds[1] ; array of <pointers to $tagCMD>
Global $tagCMD = "char Name[128]; ubyte CmdLen; byte Cmd[100]"


For $i = 1 To 10
    $new = DllStructCreate($tagCMD)
    $ptr = DllStructGetPtr($new)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ptr = ' & $ptr & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    Local $index = _ArraySearch ( $Cmds, $ptr )
    While $index <> -1 
        ; $ptr is already in array, so create a new struct
        ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $index = ' & $index & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
        $new = DllStructCreate($tagCMD)
        $ptr = DllStructGetPtr($new)
        ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ptr = ' & $ptr & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
        $index = _ArraySearch ( $Cmds, $ptr )
    WEnd     
    
    _ArrayAdd ( $Cmds, $ptr )
Next

_ArrayDisplay ( $Cmds )

Anyone got an idea, what's wrong here?

Thanks in advance

Share this post


Link to post
Share on other sites



Hi all,

I'm having problems with DllStructCreate:

When running the following script, it enters an infinite loop, because DllStructCreate returns

always the same memory address (obtained with DllStructGetPtr() )

#include <Array.au3>

Global $Cmds[1] ; array of <pointers to $tagCMD>
Global $tagCMD = "char Name[128]; ubyte CmdLen; byte Cmd[100]"


For $i = 1 To 10
    $new = DllStructCreate($tagCMD)
    $ptr = DllStructGetPtr($new)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ptr = ' & $ptr & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    Local $index = _ArraySearch ( $Cmds, $ptr )
    While $index <> -1 
        ; $ptr is already in array, so create a new struct
        ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $index = ' & $index & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
        $new = DllStructCreate($tagCMD)
        $ptr = DllStructGetPtr($new)
        ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ptr = ' & $ptr & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
        $index = _ArraySearch ( $Cmds, $ptr )
    WEnd     
    
    _ArrayAdd ( $Cmds, $ptr )
Next

_ArrayDisplay ( $Cmds )

Anyone got an idea, what's wrong here?

Thanks in advance

Can you explain what you want to do? I don't undrstand why you keep recreating the same struct for example.

This would make some sense to me.

#include <Array.au3>

Global $Cmds[10]; array of <pointers to $tagCMD>
Global $New[10]
Global $tagCMD = "char Name[128]; ubyte CmdLen; byte Cmd[100]"


For $i = 0 To 9
    $new[$i] = DllStructCreate($tagCMD)
      _ArrayAdd($cmds,DllstructGetPtr($new[$i])
Next

_ArrayDisplay ( $Cmds )

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.

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

martin, first of all thanks for the quick response!

Basically i want exactly what you proposed, namely an array

of pointers to my structure.

What I don't unterstand, havever, is that consecutive calls to

DllStructCreate() always rerturn the same memory address.

In my understanding, there should be a new memory allocation with every

call to DllStructCreate(), because I do not pass a pointer (as 2nd arg) to the function.

Am i wrong with that assumption?

thanks

Edited by manni

Share this post


Link to post
Share on other sites

The memory address is the same because the struct is destroyed along with the handle for the struct. AutoIt doesn't care if you have a pointer to the struct stored somewhere. So what you have to do is save the handle to the struct somewhere, where it doesn't get destroyed until you want to.


Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites

Ahhhhh! Now I got it.

That works:

#include <Array.au3>

Global $Cmds[1]; array of <pointers to $tagCMD>
Global $tagCMD = "char Name[128]; ubyte CmdLen; byte Cmd[100]"


For $i = 0 To 9
    _ArrayAdd($cmds,DllStructCreate($tagCMD) )
Next

For $i = 0 To 9
    $struct = $Cmds[$i]
    $ptr = DllStructGetPtr ( $struct )
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ptr = ' & $ptr & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
Next

Thanks for your replies!

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

The memory address is the same because the struct is destroyed along with the handle for the struct. AutoIt doesn't care if you have a pointer to the struct stored somewhere. So what you have to do is save the handle to the struct somewhere, where it doesn't get destroyed until you want to.

Well I think manni has a point.

If you create a label for example

GUICreate("nothing")
$lab = GuiCtrlCreateLabel("one",30,40,100,22)
consolewrite($lab & @CR)
$lab = GuiCtrlCreateLabel("two",30,40,100,22)
consolewrite($lab & @CR)

then the second label doesn't replace the first. Nothing explicitly destroys the struct so it would be reasonable to assume that it still exists.

IMO it could be argued either way, but as it is you just have to learn that dllstructs are different I suppose.

BIG EDIT:

That is all wrong!

The struct isn't destroyed and the pointer isn't the same

$a = dllstructcreate("int")
ConsoleWrite(DllStructGetPtr($a) & @CRLF)
$a = dllstructcreate("int")
ConsoleWrite(DllStructGetPtr($a) & @CRLF)

I'll look at manni's code again.

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.

Share this post


Link to post
Share on other sites

The problem was not that dllstructs were getting overwritten, but that the script was wrong.

Here is what I think it should have been

#include <Array.au3>

Global $Cmds[1] = [0]; array of <pointers to $tagCMD>
Global $tagCMD = "char Name[128]; ubyte CmdLen; byte Cmd[100]"

Global $new,$ptr
For $i = 1 To 10
    $new = DllStructCreate($tagCMD)
    $ptr = DllStructGetPtr($new)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ptr = ' & $ptr & @crlf & '>Error code: ' & @error & @crlf);### Debug Console
     _ArrayAdd ( $Cmds, $ptr )
    Local $index = _ArraySearch ( $Cmds, $ptr )
    ConsoleWrite("line 12 $index =" & $index & @CRLF)
    While $index = -1
       ; $ptr is already in array, so create a new struct
        ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $index = ' & $index & @crlf & '>Error code: ' & @error & @crlf);### Debug Console
        $new = DllStructCreate($tagCMD)
        $ptr = DllStructGetPtr($new)
        _ArrayAdd ( $Cmds, $ptr )
        ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ptr = ' & $ptr & @crlf & '>Error code: ' & @error & @crlf);### Debug Console
        $index = _ArraySearch ( $Cmds, $ptr )
    WEnd    
   
    
Next

_ArrayDisplay ( $Cmds )

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.

Share this post


Link to post
Share on other sites

The problem was not that dllstructs were getting overwritten, but that the script was wrong.

Here is what I think it should have been

#include <Array.au3>

Global $Cmds[1] = [0]; array of <pointers to $tagCMD>
Global $tagCMD = "char Name[128]; ubyte CmdLen; byte Cmd[100]"

Global $new,$ptr
For $i = 1 To 10
    $new = DllStructCreate($tagCMD)
    $ptr = DllStructGetPtr($new)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ptr = ' & $ptr & @crlf & '>Error code: ' & @error & @crlf);### Debug Console
     _ArrayAdd ( $Cmds, $ptr )
    Local $index = _ArraySearch ( $Cmds, $ptr )
    ConsoleWrite("line 12 $index =" & $index & @CRLF)
    While $index = -1
      ; $ptr is already in array, so create a new struct
        ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $index = ' & $index & @crlf & '>Error code: ' & @error & @crlf);### Debug Console
        $new = DllStructCreate($tagCMD)
        $ptr = DllStructGetPtr($new)
        _ArrayAdd ( $Cmds, $ptr )
        ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ptr = ' & $ptr & @crlf & '>Error code: ' & @error & @crlf);### Debug Console
        $index = _ArraySearch ( $Cmds, $ptr )
    WEnd    
   
    
Next

_ArrayDisplay ( $Cmds )

martin, when I run your proposed script and look at the output from _ArrayDisplay(),

I see that, the odd entries Array[1], Array[3], Array[5] ... are all the same

and the even entries are all the same, i.e they point to the same memory location.

Any ideas about that?

thanks

Share this post


Link to post
Share on other sites

BIG EDIT:

That is all wrong!

The struct isn't destroyed and the pointer isn't the same

$a = dllstructcreate("int")
ConsoleWrite(DllStructGetPtr($a) & @CRLF)
$a = dllstructcreate("int")
ConsoleWrite(DllStructGetPtr($a) & @CRLF)

I'll look at manni's code again.

I cannot test since I'm at a public pc, but I can say that I'm pretty sure the first struct is destroyed. The reason for the memory address change can be anything. Maybe AutoIt allocates new memory between the calls and more likely because when you call DllStructCreate() $a still exists. it doesn't get overwrited until the function returns.

Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites

I cannot test since I'm at a public pc, but I can say that I'm pretty sure the first struct is destroyed. The reason for the memory address change can be anything. Maybe AutoIt allocates new memory between the calls and more likely because when you call DllStructCreate() $a still exists. it doesn't get overwrited until the function returns.

Ok, I believe that I haven't understood this yet but I don't think your explanation is correct either.

Try this for example

For $c = 1 To 16
    $a = DllStructCreate("int")
    ConsoleWrite(DllStructGetPtr($a) & @CRLF)
    While 1
        $a = DllStructCreate("int")
        ConsoleWrite(DllStructGetPtr($a) & @CRLF)
        ExitLoop
    WEnd
Next

This produced

0x01431FF0

0x003DDD18<-------repeated block start

0x01431F58

0x003DDE28

0x014312F0

0x01431FE0

0x003DDD08

0x003DBDC8

0x003DDD18<-------repeated block start

0x01431F58

0x003DDE28

0x014312F0

0x01431FE0

0x003DDD08

0x003DBDC8

0x003DDD18<-------repeated block start

0x01431F58

0x003DDE28

0x014312F0

0x01431FE0

0x003DDD08

0x003DBDC8

0x003DDD18<-------repeated block start

0x01431F58

0x003DDE28

0x014312F0

0x01431FE0

0x003DDD08

0x003DBDC8

0x003DDD18<-------repeated block start

0x01431F58

0x003DDE28

I don't understand that either :)


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.

Share this post


Link to post
Share on other sites

I really don't know what you're going with these numbers martin. They're kinda irrelevant since it's up to windows and autoit to give us pointers that points to valid blocks of memory we really shouldn't care if a specific number returns after a few allocations and deallocations. Made a small example also.

$a=DllStructCreate("char[8];")
DllStructSetData($a,1,"Andreas")
$strptr=DllStructGetPtr($a)
ConsoleWrite("Pointer to string is: "&$strptr&@CRLF); Output the pointer


$a=DllStructCreate("int;"); The struct is created. However since the first $a is not destroyed until DllStructCreate() is done it's a new pointer
DllStructSetData($a,1,1234); Set some random data
$intptr=DllStructGetPtr($a) 
ConsoleWrite("Pointer to int is: "&$intptr&@CRLF); Outputs second data. This pointer could be anything and we really shouldn't care how it's connected to the first pointer


; even though they have different pointers, $strptr doesn't point to any valid data anymore (could even crash)
; This is because AutoIt has returned control of this block of memory to windows.
$b=DllStructCreate("char[8];",$strptr)
ConsoleWrite(DllStructGetData($b,1)&@CRLF)

I'm not really sure what you mean though..


Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites

I really don't know what you're going with these numbers martin. They're kinda irrelevant since it's up to windows and autoit to give us pointers that points to valid blocks of memory we really shouldn't care if a specific number returns after a few allocations and deallocations. Made a small example also.

$a=DllStructCreate("char[8];")
DllStructSetData($a,1,"Andreas")
$strptr=DllStructGetPtr($a)
ConsoleWrite("Pointer to string is: "&$strptr&@CRLF); Output the pointer


$a=DllStructCreate("int;"); The struct is created. However since the first $a is not destroyed until DllStructCreate() is done it's a new pointer
DllStructSetData($a,1,1234); Set some random data
$intptr=DllStructGetPtr($a) 
ConsoleWrite("Pointer to int is: "&$intptr&@CRLF); Outputs second data. This pointer could be anything and we really shouldn't care how it's connected to the first pointer


; even though they have different pointers, $strptr doesn't point to any valid data anymore (could even crash)
; This is because AutoIt has returned control of this block of memory to windows.
$b=DllStructCreate("char[8];",$strptr)
ConsoleWrite(DllStructGetData($b,1)&@CRLF)

I'm not really sure what you mean though..

I think the problem is that I've been confused [even more than I normally am :)]

I had forgotten that the way to destroy a dll struct is to assign the struct variable to 0 like this

$astruct = DllSTructCreate("int")
$astruct = 0;delete the struct

or assigning the struct variable to any value destroys the old struct. Which is what you were trying to tell me. But I was trying to equate this, as I said in an earlier post, to the case where you create a label for eaxample. Assigning the variable to a new label doesn'y destroy the old label. However, a struct is not an object like a window and I was being daft :).

Sorry to waste your time with my confusion, and thanks for your time. When I grow up I hope to learn how to write programs.


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.

Share this post


Link to post
Share on other sites

I think the problem is that I've been confused [even more than I normally am :) ]

I had forgotten that the way to destroy a dll struct is to assign the struct variable to 0 like this

$astruct = DllSTructCreate("int")
 $astruct = 0;delete the struct

or assigning the struct variable to any value destroys the old struct. Which is what you were trying to tell me. But I was trying to equate this, as I said in an earlier post, to the case where you create a label for eaxample. Assigning the variable to a new label doesn'y destroy the old label. However, a struct is not an object like a window and I was being daft :) .

Sorry to waste your time with my confusion, and thanks for your time. When I grow up I hope to learn how to write programs.

Don't mention it. It's great to be able to give back some of the help I have received from you :)

Broken link? PM me and I'll send you the file!

Share this post


Link to post
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
Sign in to follow this  
Followers 0