How to get pointer to a string stored in an array element?
How to get pointer to a string stored in an array element?
As the title says!
Re: How to get pointer to a string stored in an array element?
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
Re: How to get pointer to a string stored in an array element?
@iPhilip,
thanks, but it doesn't.apparently returns the address of a temporary buffer which will be reused by the script.
thanks, but it doesn't.
Code: Select all
StrPtr(a[1])
Code: Select all
Arr := ["Hello!", "Olleh!"]
Ptr1 := StrPtr(Arr[1])
Ptr2 := StrPtr(Arr[2])
MsgBox("This should be 'Hello!': " . StrGet(Ptr1))
-
- Posts: 4336
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: How to get pointer to a string stored in an array element?
Using bruteforce:
However, so far it only works for 64 bits.
Code: Select all
arr := ['a', 'b', 'c', 'd', 'e']
pObj := ObjPtr(arr)
Loop arr.Length {
MsgBox StrGet(NumGet(NumGet(pObj + A_PtrSize*4, 'Ptr') + A_PtrSize*2*(A_Index - 1), 'Ptr') + A_PtrSize*2)
}
Re: How to get pointer to a string stored in an array element?
Hi @teadrinker,
thanks. But there's someone called @lexikos always objecting the use of undocumented implementation details.
thanks. But there's someone called @lexikos always objecting the use of undocumented implementation details.
-
- Posts: 4336
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: How to get pointer to a string stored in an array element?
I don't think there is a "legal" way.
For both:
For both:
Code: Select all
arr := ['a', 'b', 'c', 'd', 'e']
pObj := ObjPtr(arr)
Loop arr.Length {
MsgBox StrGet(NumGet(NumGet(pObj + 8 + A_PtrSize*3, 'Ptr') + 16*(A_Index - 1), 'Ptr') + A_PtrSize*2)
}
Re: How to get pointer to a string stored in an array element?
I agree. I looked for a replacement for Obj.GetAddress() but it seems to be a thing for the wish list.
Re: How to get pointer to a string stored in an array element?
This approach seems to work:
Code: Select all
Arr := ["Hello!", "Olleh!"]
o1 := Buffer(20)
StrPut(Arr[1], o1)
o2 := Buffer(20)
StrPut(Arr[2], o2)
MsgBox("This should be 'Hello!': " . StrGet(o1))
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
-
- Posts: 4336
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: How to get pointer to a string stored in an array element?
@iPhilip
Ha-ha, no. o1.ptr is not the actual address of the first array item.
Ha-ha, no. o1.ptr is not the actual address of the first array item.
Re: How to get pointer to a string stored in an array element?
@iPhilip, thanks. Your suggestion actually shows the problem. You have to copy the string to get a valid reliable pointer.
Re: How to get pointer to a string stored in an array element?
@teadrinker, You are right. That was the only way I could figure to save an address to the string.teadrinker wrote: ↑09 May 2023, 11:48@iPhilip
Ha-ha, no. o1.ptr is not the actual address of the first array item.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
Re: How to get pointer to a string stored in an array element?
I guess this should go into a wish list request. It seems important, though @lexikos might look for a use case to justify the effort.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
Re: How to get pointer to a string stored in an array element?
Hi @iPhilip,
my use case:
The TaskDialogIndirect() funktion expects a TASKDIALOGCONFIG structure containing pointers to arrays of TASKDIALOG_BUTTON structures which contain the ID and a pointer to the caption string of the buttons.
In v1, it was possible to use an AHK array for the button captions and get the pointers using Array.GetAddress(Index). GetAddress() has been removed in v2. The new funktion StrPtr() cannot be used because for array elements it obviously returns a pointer to an internal buffer which AHK might reuse as soon as required. So I have to copy the strings from the array, e.g.
It's neither convenient nor performant respectively resource saving.
@lexikos, any chance for a change?
my use case:
The TaskDialogIndirect() funktion expects a TASKDIALOGCONFIG structure containing pointers to arrays of TASKDIALOG_BUTTON structures which contain the ID and a pointer to the caption string of the buttons.
In v1, it was possible to use an AHK array for the button captions and get the pointers using Array.GetAddress(Index). GetAddress() has been removed in v2. The new funktion StrPtr() cannot be used because for array elements it obviously returns a pointer to an internal buffer which AHK might reuse as soon as required. So I have to copy the strings from the array, e.g.
Code: Select all
Chars := 0
For Str In Radios ; AHK array of button captions
Chars += StrLen(Str) + 1
Tmp := Buffer(Chars * 2, 0)
Addr1 := Tmp.Ptr
RBArr := Buffer(TDBSize * RBCount, 0) ; C array of TASKDIALOG_BUTTON structures
Addr2 := RBArr.Ptr
For I, V In Radios {
Len := StrPut(V, Addr1)
Addr2 := NumPut("Int", MinRID + A_Index, "Ptr", Addr1, Addr2)
Addr1 += Len
}
@lexikos, any chance for a change?
Re: How to get pointer to a string stored in an array element?
I think that makes sense based on the documentation for StrPtr since it says, "The address of a temporary string is valid only until evaluation of the overall expression or function call statement is completed...". It doesn't allow for storing of the address and then use later. Since you're trying to put it into a structure first, then send it later it won't work. Bummer.
Re: How to get pointer to a string stored in an array element?
In my opinion, I would go with the hacky route from teadrinker, or force the use of a sentinel.
You need one sentinel per StrPtr, and this "minimizes" any damage done. (Er, basically just name your array element and pass that onto strptr)
Code: Select all
#Requires AutoHotkey v2.0
Arr := ["Hello!", "Olleh!"]
Ptr1 := StrPtr(_1 := Arr[1])
Ptr2 := StrPtr(_2 := Arr[2])
MsgBox("This should be 'Hello!': " . StrGet(Ptr1))
Re: How to get pointer to a string stored in an array element?
But to clarify, StrPtr would only operate on a string. You can't really pass StrPtr(Arr[1]), as it's technically a race condition. You're evaluating Arr[1] into some temporary buffer, and StrPtr gets the address of the temporary buffer. You really should iterate through the object pointer as teadrinker has shown, in lieu of GetAddress.
I think the cleanest approach is to take teadrinker's code, and make it a method of your array and call that GetAddress or GetString
I think the cleanest approach is to take teadrinker's code, and make it a method of your array and call that GetAddress or GetString
Re: How to get pointer to a string stored in an array element?
@iseahound, Thank you for your explanation. It's very helpful. Can you explain what you mean by race condition in this context? My understanding is that a race condition occurs when two or more threads can access shared data and they try to change it at the same time.iseahound wrote: ↑11 May 2023, 14:05But to clarify, StrPtr would only operate on a string. You can't really pass StrPtr(Arr[1]), as it's technically a race condition. You're evaluating Arr[1] into some temporary buffer, and StrPtr gets the address of the temporary buffer. You really should iterate through the object pointer as teadrinker has shown, in lieu of GetAddress.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
Re: How to get pointer to a string stored in an array element?
I would make a suitable object for the job, eg,
Cheers.
Code: Select all
class str_arr extends array {
; also do __new if desired
__item[k]{
get => strget(super[k])
set {
b := buffer(strlen(value) * 2 + 2)
strput value, b
return super[k] := b
}
}
ptr(k) => super[k].ptr
}
Re: How to get pointer to a string stored in an array element?
The temporary buffer can be reused by the next variable assignment. That means there is a race condition, in line with your definition. However, this technically will never occur, as StrPtr() is the next call, and the function that uses the string pointer afterwards.
I think Lexikos also says that it wont be a race condition (implicitly).
I think Lexikos also says that it wont be a race condition (implicitly).
Notice the use of a temporary string buffer here.https://www.autohotkey.com/docs/v2/v2-changes.htm#EnvUpdate wrote:Code: Select all
SendMessage(0x1A, 0, StrPtr("Environment"), 0xFFFF)
Re: How to get pointer to a string stored in an array element?
Not really though. StrPtr on a literal will be valid for the length of the process
Who is online
Users browsing this forum: Google [Bot], mikeyww, niCode, william_ahk and 67 guests