help with pointers, structures, and a possible bug with LSet

Just starting out? Need help? Post your questions and find answers here.
nsstudios
Enthusiast
Enthusiast
Posts: 274
Joined: Wed Aug 28, 2019 1:01 pm
Location: Serbia
Contact:

help with pointers, structures, and a possible bug with LSet

Post by nsstudios »

Hi all,

I was wondering if someone can help me with a few things that have me stumped:
• Is there an easy way to get the address of a literal that is not a string?
With strings I can do
*pointer=@"test"
but that does not seem to be the case for
*pointer=@1
so is there a way to do it without creating a variable first like:
tmp=1
*pointer=@tmp
?
Also, is there an easier way to pass structures than having to define them first like:
tmp.string\s="test"
*pointer.string=@tmp
?

• Is there a way to get the type of a variable by its address, i.e., if I sometimes have:
*pointer=@string_var
, but other times
*pointer=@int_var
. How can I find out whether *pointer contains the address of a string or int so that I can do either peekS or peekI, and avoid error when I try to access the wrong one?

• How do I check if a structure field is set?
structure var
s.s
i.i
endStructure
v.var
v\s="test"
How would I now find out which of them are set (maybe both?)
Checking for #null and #null$ is unreliable because #null would return true for 0, and #null$ would return true for "" (I sometimes wish pb had the equivalent of ===).

• What exactly do import "" and importC "" do?
I've used import and importC before to import functions from libraries, but what does importing from nothing do?

• How can I find out if my notify icon already exists (winapi)?
I display a help balloon in my program by using Shell_NotifyIcon_, and currently I have this:
procedure balloon()
Static update=0
If update
Shell_NotifyIcon_(#NIM_MODIFY, my_notifyicon)
Else
Shell_NotifyIcon_(#NIM_ADD, my_notifyicon)
update=1
EndIf
EndProcedure
, but that seems to cause the balloons not to appear sometimes until the program is restarted.
Is there a reliable way of detecting whether my icon already exists?
Am I even supposed to be modifying it instead of removing it and re-adding it?
My program displays the notifications only once in a while to alert the user about something, I don't need the icon for anything else...

• LSet function confuses me.
The documentation says: “If the string is longer than the specified length, it will be truncated starting from the left side of the string.” which is the opposite of the RSet function (which says: “If the string is longer than the specified length, it will be truncated starting from the right side of the string.”), yet the function actually truncates from the right side, just like RSet, and the example actually is the same truncating-wise for both functions.
Debug LSet("LongString", 4) ; will display "Long"
even though it should display “ring” for LSet.
Sounds to me like there's either a bug in the LSet, or the manual is misleading.

Any help would be greatly appreciated.
User avatar
spikey
Enthusiast
Enthusiast
Posts: 586
Joined: Wed Sep 22, 2010 1:17 pm
Location: United Kingdom

Re: help with pointers, structures, and a possible bug with

Post by spikey »

nsstudios wrote:Is there a way to do it without creating a variable first like:
If you put the constant into a datasection and label it you can get the address.
What you are actually doing though is creating a variable by a different route, with a constant value, so the precise answer would be 'no'.

Code: Select all

Define *Int = ?D1
Debug *Int

DataSection
  D1:
  Data.I 1
EndDataSection
nsstudios wrote:Is there an easier way to pass structures than having to define them first
You can allocate a pointer and populate it directly. Personally I'd say it doesn't particularly meet the 'easier' criterion though.

Code: Select all

Define *Pointer = AllocateMemory(SizeOf(Integer))
PokeI(*Pointer, 1234)
Debug PeekI(*Pointer)
nsstudios wrote:Is there a way to get the type of a variable by its address
No. If you want this information you would have to keep track of it yourself separately.
The byte data of a string in memory is indistinguishable from a half dozen integers, say.
You won't get an error if you PeekS on an integer or vice versa, you just won't get back anything sensible.
Personally I'd say it would be better to use multiple pointers to ensure this type of ambiguity doesn't arise.
nsstudios wrote:How do I check if a structure field is set?
For the same reason as above you would need to have a separate flag to indicate the status of (a) particular member(s).
nsstudios wrote:What exactly do import "" and importC "" do?
Some functions exist in the standard library but aren't normally public.
For example PBs internal object creation functions get called when you add a gadget to a window but normally aren't visible to the programmer.
This allows them to be made public, if you need to use them.
nsstudios wrote:LSet function confuses me. Sounds to me like there's either a bug in the LSet, or the manual is misleading.
Yep, something seems to have gone wrong there somewhere. I've posted a bug report.
nsstudios
Enthusiast
Enthusiast
Posts: 274
Joined: Wed Aug 28, 2019 1:01 pm
Location: Serbia
Contact:

Re: help with pointers, structures, and a possible bug with

Post by nsstudios »

Thanks a lot for the speedy reply and help. :)

Is there a way to see the functions that aren't publically exposed?
So far I've only seen people on forums use import/importC "", but how would I get the list of possible functions that I could import?

The reason I was asking for an easier way to get the address of an integer is because I've been trying to make an iif-like function that would work with both ints and strings, so having to first define a variable is really not what I want.
Here's what I tried:
;{
Procedure iif_(expression, *true, *false)
If expression
ProcedureReturn *true
EndIf
ProcedureReturn *false
EndProcedure
Macro iif(_expression_, _true_, _false_, _type_=s)
peek#_type_(iif_(Bool(_expression_), _true_, _false_))
EndMacro
a=1
;I can do string just fine
b.s="the state is: "+iif(a=1, @"on", @"off")
Debug b
;int does not work the way I'm trying to do it
;I guess I would need a function that would give me the address or something...
;c=iif(a=1, @256, @0, i)
;I can do this, but it defeats the whole purpose:
Define t=256, f=0
c=iif(a=1, @t, @f, i)
Debug c
;}
Silly example, but I hope it shows what I'm trying to do.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: help with pointers, structures, and a possible bug with

Post by wilbert »

For numbers, you could consider something like

Code: Select all

Macro IIF(expression, true, false)
  ((false) + ((true)-(false))*Bool(expression))
EndMacro

Debug IIF(3 > 4, 3, 5)
Debug IIF(4 > 3, 3.5, 5)
Debug 5 + IIF("a" > "b", 1, 0)
Debug 5 + IIF("b" > "a", 1, 0)
Windows (x64)
Raspberry Pi OS (Arm64)
nsstudios
Enthusiast
Enthusiast
Posts: 274
Joined: Wed Aug 28, 2019 1:01 pm
Location: Serbia
Contact:

Re: help with pointers, structures, and a possible bug with

Post by nsstudios »

Thanks for a great idea!
I guess I can then have a separate function that does that, and have it call either the string or numeric function based on the type.
Post Reply