how to get a variable pointer?

Blitz3D Forums/Blitz3D Programming/how to get a variable pointer?

MusicianKool(Posted 2011) [#1]
other then fastpointer how do you get a variable pointer?


Yasha(Posted 2011) [#2]
Erm... given that pointer support is added by FastPointer, you're not going to have much luck doing it without...

However - it depends. What do you want to do? B3D doesn't have full pointer support, but it does have a few techniques that are good enough in most circumstances. There may be a suitable alternative, as long as you don't need it to do everything.

e.g. The most common use for variable pointers is to create out-parameters:

// some_lib.c

static int private_x, private_y;

void get_coords(int * x, int * y) {
    *x = private_x;
    *y = private_y;
}

// main.c
...
int x, y;
get_coords(&x, &y);
do_something_with_values(x, y);
...


You can do almost exactly the same thing in B3D using arrays:

; some_lib.bb

Global SL_private_x_, SL_private_y_

Function GetCoords(x[0], y[0])
    x[0] = SL_private_x_
    y[0] = SL_private_y_
End Function

; main.bb
...
Local x[0], y[0]
GetCoords x, y
DoSomethingWithValues x[0], y[0]
...


The most important difference is that you can't do it to arbitrary variables: the code calling the function needs to have declared arrays for use as out-parameters, so it's not quite as flexible (although in C and C# you still need to explicitly pass the variables by ref, so it's not that different); but this is easy enough to deal with and doesn't mean any major changes to your structure. Using arrays with a constant index of 0 is also really, really fast, probably about the same speed as dereferencing a pointer. Certainly much faster than messing about with banks.

In fact, depending on the compiler, those two snippets may even compile down to the same machine code!

Last edited 2011


MusicianKool(Posted 2011) [#3]
yep, that's not going to work. dang.. I need a pointer to identify an instantce of identifier. ie:

while eachin(list , Identifier)
;eachin uses the pointer to 'identifier' to define an instance of eachin and
;pass a node of list through identifier, so that eachin can do 3 things.
;1- start at the begining of list, create an instance of eachin , return 1 or 0 if the list exists or is at it's end.
;2- the pointer of Identifier becomes the Identity of eachin so that nested eachin's act independently unless the same identifier is used.
;3-the identifier contains the data in the current node so it can be accessed by using Identifier as normal.
wend

so basically acts like
for this.type = each type

next
except the list only contains what you put into that list.
unlike b3d type list's where the list contains every type created,
and is comprised only of type's.


Yasha(Posted 2011) [#4]
I... think ...I see what you want to do. Basically define a new kind of iterator? And no. 2 is the obstacle preventing you from doing this with arrays, right?

Extending a language's syntax really is something for languages with powerful macro systems. You could do something like this pretty easily using the C Pre-Processor (but for that, you'd have to use the C Pre-Processor, which is a problem all by itself), or Lisp, which doesn't help you at all... or pretty much any language with lambdas... basically you've hit one of the hard limits of B3D with this question!

The best I can suggest is that you use a helper type to create explicit Iterator objects, where each Iterator contains a Value field where the value for that iteration is stored. You can test objects for identity easily enough, so create a new identifier before each EachIn loop and delete it after it ends. Within the while loop you'd have to use it\Value to get at the value.

Even FastPointer wouldn't let you do it the way you've outlined above, as FastPointer can't take var pointers as part of an expression, only as a statement block. And I don't know of any other way to get at var pointers from B3D.

Also, before you do too much work in this area, take a look here: http://www.blitzbasic.com/Community/posts.php?topic=86730

Might not have exactly what you want, but it will certainly be a powerful starting point. It has list container classes at any rate.

Last edited 2011


Subirenihil(Posted 2011) [#5]
Banks. If 'Identifier' is a bank, then it is in essence a pointer to whatever data you want to put into it. If your data is mixed variable types, then this may be your best bet.

However, types do have a 'pointer' to them that is accessible. If you want to make multiple lists of the same 'type' that are searchable independent of each other, add a pointer to the previous and next items in the list.

Banks provide the more robust solution, while type pointers (refered to as 'handles' in B3D, you can use these via 'Handle' and 'Object' commands) require little change to your existing framework.


Yasha(Posted 2011) [#6]
I actually rather liked my own suggestion about Iterator objects. Here's a quick example of doing it that way:



Thanks for the idea to use EachIn as the parameter to While. It's simple and elegant, and I would never have thought of doing it that way myself! I'll probably end up using something like this quite a lot... (probably strongly-typed though).


---


@Subirenhil What do you mean by "robust"? That's pretty much the opposite of how I would describe banks. You should never be using banks for structured data if you can possibly avoid it.


Subirenihil(Posted 2011) [#7]
Robust as in more multi-purpose, usable in a wider range of applications. Not necessarily as easy to implement or harder to break (I'd say it's a lot easier to break if you're not careful).

Good example btw, nice use of Handle/Object commands.

I find banks easy to deal with - treat them like you would a file and they are incredibly flexible.

Still think Yasha probably has what you're looking for.


MusicianKool(Posted 2011) [#8]
@Yasha
that's funny, I have the LL working fully in freebasic and am using it all the time, using integer/pointer as the iterator the way i described before. what you have is basically the same thing via the iterator type, but i wanted it to be done without adding more code to a project via a library (i get lost when there is to much code no matter how simple it is to read or even if its an include file). hmm, if you can pass type pointers in blitz.. naw i wont worry about it, working on something else at the moment cant get distracted.

Last edited 2011


MusicianKool(Posted 2011) [#9]
Well, I think Blitz3d needs a fully working double Linked List. here is an update with Yasha's iterator type. but i'm having problems figuring out how to delete an element of a list. Type's are handled very differently in blitz3d then how i originally made the linked list, and it's confusing me.

I'm sure this isn't suitable for all situations and is unstable. Delete_ doesn't work correctly though it should.



Yasha(Posted 2011) [#10]
Don't know if this is exactly what you mean, but the full version of the above short example I dumped into the code archives a couple of days ago: http://www.blitzbasic.com/codearcs/codearcs.php?code=2873

It has IteratorRemove as a separate function from ListRemove to keep things simple at the implementation end.


MusicianKool(Posted 2011) [#11]
i have the same problem with your code as with the code i put above concerning the removal of an element during an EachIn loop .
removing an element within a While EachIn leads to a memory access violation. Again, it shouldn't cause an error, the code is sound, but it does.
Example:
Local List1.LList = CreateList()

Local i
For i = 1 To 10
	ListAddLast List1,i
Next

Local List2.LList = CreateList()
For i = 1 To 10
	ListAddLast List2,i*100
Next

Local i1.Iterator = GetIterator(List1),i2.Iterator = GetIterator(List2)
While EachIn(i1)
	Print i1\Value
	While EachIn(i2)
		Print i2\Value
	Wend
	;the next 2 lines lead to the same error within EachIn
	If i1\Value = 3 Then IteratorRemove(i1)
	;ListRemove(List1,3) 
Wend

WaitKey()



Yasha(Posted 2011) [#12]
This is actually correct behaviour, believe it or not!

My particular implementation of EachIn means that at the end of a loop, the iterator is immediately disconnected from the list and is no longer "alive". It's not deleted, on the understanding that most programs will develop a fixed pool of Iterators and this saves time and memory. So after the first run of the outer loop, i2 is no longer connected to anything - as far as it's aware, its job is done and it's back to the pool.

This means that you need to call GetIterator every time you enter the EachIn loop. You unfortunately can't pre-grab an iterator for the inner loop outside both loops. The idea was to write code like this:
Local i2.Iterator = GetIterator(List2) : While EachIn(i2)


Since you should never be using the Iterator outside of the loop, logic-wise this should never be a problem. You might take offence at the performance implications, I guess (the main way to solve this is probably to manually keep the Iterator pool small).

Last edited 2011


MusicianKool(Posted 2011) [#13]
cool, makes sense.