Return more than one variable?
Sorry if I'm late on this topic but a Structure can be manipulated like this :
When you built a set of command to access the structure you will save time if you need to modify the structure, Name of Field or Structure it's self.
I hope this small exemple can help some of you.
Regards
Guimauve
Code: Select all
;
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Structure definition >>>>>
Structure Test
a.l
b.l
EndStructure
; <<<<<<<<<<<<<<<<<<<<
; <<<<< Mutators >>>>>
Procedure SetTesta(*ObjetA.Test, a.l)
*ObjetA\a = a
EndProcedure
Procedure SetTestb(*ObjetA.Test, b.l)
*ObjetA\b = b
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Observators >>>>>
Procedure.l GetTesta(*ObjetA.Test)
ProcedureReturn *ObjetA\a
EndProcedure
Procedure.l GetTestb(*ObjetA.Test)
ProcedureReturn *ObjetA\b
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Update operator >>>>>
Procedure UpdateTest(*ObjetA.Test, a.l, b.l)
SetTesta(*ObjetA, a)
SetTestb(*ObjetA, b)
EndProcedure
Code: Select all
Structure Test
Array.l[2]
EndStructure
; <<<<<<<<<<<<<<<<<<<<
; <<<<< Mutators >>>>>
Procedure SetTesta(*ObjetA.Test, a.l)
*ObjetA\Array[0] = a
EndProcedure
Procedure SetTestb(*ObjetA.Test, b.l)
*ObjetA\Array[1] = b
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Observators >>>>>
Procedure.l GetTesta(*ObjetA.Test)
ProcedureReturn *ObjetA\Array[0]
EndProcedure
Procedure.l GetTestb(*ObjetA.Test)
ProcedureReturn *ObjetA\Array[1]
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Update operator >>>>>
Procedure UpdateTest(*ObjetA.Test, a.l, b.l)
SetTesta(*ObjetA, a)
SetTestb(*ObjetA, b)
EndProcedure
Regards
Guimauve
I believe after all is said and done that the parent (not PB) application I am using to develop certain .exes with just can not handle anymore returns than just one. I would like to have multiple return values, I have been using .exe builds with command-line args. to facilitate such. But I would like to be able to parse multiple variables from a ProcedureReturn call.
I may be SOL?
I may be SOL?
Intrigued - Registered PureBasic, lifetime updates user
Heres a simple way that multiple values can be returned by a procedure:
Using a structure pointer is simple.
1. Use a static structure inside your procedure
2. manipulate it and return its pointer
3. fill another structure using a pointer

Code: Select all
Procedure.l MakePoints(Value.l)
Static Coords.POINT
Coords\x = Value & $FFFF
Coords\y = (Value >> 16) & $FFFF
ProcedureReturn @Coords
EndProcedure
*Screen.POINT = MakePoints(67109632)
Debug *Screen\x
Debug *Screen\y
1. Use a static structure inside your procedure
2. manipulate it and return its pointer
3. fill another structure using a pointer

Hmmm... I wanted to see what @Coords was holding (that's the part I need to have more than one variable returning) and it shows only one number when I did this:
Sooo... it seems I'm not understanding how this is actually returning more than one variable.
Can you dumb it down for me Kale, when you get a moment.
TIA (dunce hat going back on, I know, I know)

Code: Select all
MessageRequester("", Str(@Coords))
Can you dumb it down for me Kale, when you get a moment.
TIA (dunce hat going back on, I know, I know)


Intrigued - Registered PureBasic, lifetime updates user
Hi Intrigued,
If you don't mind me butting in until Kale gets back to the boards -
If I understand correctly, you are using PureBasic to write supporting functionality which will be compiled into a DLL. This DLL will be used by an app developed in another language, or perhaps using something that creates apps (such as GameMaker).
If so, then if the other language supports (a) structures and (b) memory addresses, you can pass multiple values via a structure. If not, you will have to make multiple calls to get the values.
Assuming it does, you create a structure (and your parent app needs an equivalent structure, or type, or record, whatever terminology it uses) and a procedure that handles the support function workload.
The above receives, from the parent, the address where your data is to be stored, and fills in the results.
The call would be along these lines:
Except, of course, using the syntax of the parent app, and however that calls a DLL - and with the parent app having a structure/type that matches your PureBasic structure/type.
If you lump those two bits of code together for PureBasic, you will see the values you want to see. Changing them in the procedure to validate.
That is one way (you give the proc the address) and many api calls use this.
Another is that the procedure returns an address to you. This leaves the DLL with a chunk of memory it has to maintain "state" with, so I prefer the first.
I hope that helped. I also hope I was on track, as it can be frustrating to be told what you already know ..
If you don't mind me butting in until Kale gets back to the boards -
If I understand correctly, you are using PureBasic to write supporting functionality which will be compiled into a DLL. This DLL will be used by an app developed in another language, or perhaps using something that creates apps (such as GameMaker).
If so, then if the other language supports (a) structures and (b) memory addresses, you can pass multiple values via a structure. If not, you will have to make multiple calls to get the values.
Assuming it does, you create a structure (and your parent app needs an equivalent structure, or type, or record, whatever terminology it uses) and a procedure that handles the support function workload.
Code: Select all
Structure myStuff
myLong.l
myDoubleWord.l
EndStructure
ProcedureDLL getMyStuff(*itIsMine.myStuff)
*itIsMine\myLong=-1
*itIsMine\myDoubleWord=1
EndProcedure
The call would be along these lines:
Code: Select all
alsoMine.myStuff
getMyStuff(@alsoMine)
Debug alsoMine\myLong
Debug alsoMine\myDoubleWord
If you lump those two bits of code together for PureBasic, you will see the values you want to see. Changing them in the procedure to validate.
That is one way (you give the proc the address) and many api calls use this.
Another is that the procedure returns an address to you. This leaves the DLL with a chunk of memory it has to maintain "state" with, so I prefer the first.
I hope that helped. I also hope I was on track, as it can be frustrating to be told what you already know ..

@}--`--,-- A rose by any other name ..
I appreciate your help. The other development platform I am using these PB created .dlls for does not allow direct access to memory. What happens is that there is an "Action" (aka. procedure) that calls the .dll. Then we pass in the Function name to the Action and any arguments. The return is set into a Global variable we can use inside our programs. The setback I found out is that it seems I can only get one return variable from a PB .dll to that other development platform. Either it's a number (Long) or a String. I want to be able to get more than one variable back from the .dll. This will help fill in the holes that the other development platform has.Dare2 wrote:Hi Intrigued,
If you don't mind me butting in until Kale gets back to the boards -
If I understand correctly, you are using PureBasic to write supporting functionality which will be compiled into a DLL. This DLL will be used by an app developed in another language, or perhaps using something that creates apps (such as GameMaker).
If so, then if the other language supports (a) structures and (b) memory addresses, you can pass multiple values via a structure. If not, you will have to make multiple calls to get the values.
Assuming it does, you create a structure (and your parent app needs an equivalent structure, or type, or record, whatever terminology it uses) and a procedure that handles the support function workload.The above receives, from the parent, the address where your data is to be stored, and fills in the results.Code: Select all
Structure myStuff myLong.l myDoubleWord.l EndStructure ProcedureDLL getMyStuff(*itIsMine.myStuff) *itIsMine\myLong=-1 *itIsMine\myDoubleWord=1 EndProcedure
The call would be along these lines:Except, of course, using the syntax of the parent app, and however that calls a DLL - and with the parent app having a structure/type that matches your PureBasic structure/type.Code: Select all
alsoMine.myStuff getMyStuff(@alsoMine) Debug alsoMine\myLong Debug alsoMine\myDoubleWord
If you lump those two bits of code together for PureBasic, you will see the values you want to see. Changing them in the procedure to validate.
That is one way (you give the proc the address) and many api calls use this.
Another is that the procedure returns an address to you. This leaves the DLL with a chunk of memory it has to maintain "state" with, so I prefer the first.
I hope that helped. I also hope I was on track, as it can be frustrating to be told what you already know ..
So, I am using PB to help expand the other platform via .dlls is what I'm muttering on about.

I hope that helps?
Another idea I just thought of was to have the (what a hack job this will be though) .dll create a temp file and then have the other development platform app. read in that data into a couple different variables.
Uhg! I wish I could just access memory with that other platform.
*pulls ears till pain sets in*
ps. I see your "multiple calls" idea. aka. multiple functions... er Procedure use I take it? Hmmm... that actually sounds like the way I might have to go, or better way to go. Thanks for you help!
Intrigued - Registered PureBasic, lifetime updates user
Ouch.
If the number is small enough, and there a few enough
perhaps you could fill the long. Eg, up to 4 x 1 byte, 2 x 2 byte, etc. So (v1 << 24) + (v2 << 16) + (v3 << 8 ) + v4, as an example (for vals 0-255).
Or use the string?
Does it have a good way of getting substrings. Eg an Array = Split(String,character) or StringField type approach? If so, perhaps you could fill a string with Str(r1) + "," + Str(r2) [+ ....]
Otherwise, I pass. Sorry!
If the number is small enough, and there a few enough

Or use the string?
Does it have a good way of getting substrings. Eg an Array = Split(String,character) or StringField type approach? If so, perhaps you could fill a string with Str(r1) + "," + Str(r2) [+ ....]
Otherwise, I pass. Sorry!
@}--`--,-- A rose by any other name ..
If this helps it uses the LUA language as it's scripting engine. There are something like 600 Actions (they call them Actions, instead of functions) innate to the platform. But, I have used "pure" LUA code inside of my apps. Also, I have seen there is a LUA library for PB. I wonder if that would help any. More... "hmmm"Dare2 wrote:Ouch.
If the number is small enough, and there a few enoughperhaps you could fill the long. Eg, up to 4 x 1 byte, 2 x 2 byte, etc. So (v1 << 24) + (v2 << 16) + (v3 << 8 ) + v4, as an example (for vals 0-255).
Or use the string?
Does it have a good way of getting substrings. Eg an Array = Split(String,character) or StringField type approach? If so, perhaps you could fill a string with Str(r1) + "," + Str(r2) [+ ....]
Otherwise, I pass. Sorry!

Intrigued - Registered PureBasic, lifetime updates user
Thanks again for your help. It's helped me look at the situation in a different light.Dare2 wrote:Aha, for this we need * drumroll * FloHimself.
He is a genius with this, and seems pretty easy going and helpful so I don't think it would be out of line to PM him.
However it also seems like you're cracking into the workarounds. Success to you!
*thumbs up*
Intrigued - Registered PureBasic, lifetime updates user
-
- Enthusiast
- Posts: 229
- Joined: Wed May 14, 2003 3:38 pm
- Location: Lüneburg - Germany
Just discovered this thread and haven't read all... but sounds to me youIntrigued wrote:The other development platform I am using these PB created .dlls for does not allow direct access to memory. What happens is that there is an "Action" (aka. procedure) that calls the .dll...
are trying to write something like a *lua extension* with PB?
My favorite numbers: 09 F9 11 02 9D 74 E3 5B D8 41 56 C5 63 56 88 C0