Return more than one variable?

Just starting out? Need help? Post your questions and find answers here.
Intrigued
Enthusiast
Enthusiast
Posts: 501
Joined: Thu Jun 02, 2005 3:55 am
Location: U.S.A.

Post by Intrigued »

I will be utilizing such in a .dll, with ProcedureDLL. Is there anything that needs to changed? As I want to have a .dll utilized by by another application building platform.

TIA and for the suggestions.
Intrigued - Registered PureBasic, lifetime updates user
Intrigued
Enthusiast
Enthusiast
Posts: 501
Joined: Thu Jun 02, 2005 3:55 am
Location: U.S.A.

Post by Intrigued »

*A hush befalls the auditorium*

:wink:
Intrigued - Registered PureBasic, lifetime updates user
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Post by Guimauve »

Sorry if I'm late on this topic but a Structure can be manipulated like this :

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
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.

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
I hope this small exemple can help some of you.

Regards

Guimauve
Intrigued
Enthusiast
Enthusiast
Posts: 501
Joined: Thu Jun 02, 2005 3:55 am
Location: U.S.A.

Post by Intrigued »

Thanks Guimauve! I'm off to print and study such.

Thanks again!
Intrigued - Registered PureBasic, lifetime updates user
Intrigued
Enthusiast
Enthusiast
Posts: 501
Joined: Thu Jun 02, 2005 3:55 am
Location: U.S.A.

Post by Intrigued »

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?
Intrigued - Registered PureBasic, lifetime updates user
Kale
PureBasic Expert
PureBasic Expert
Posts: 3000
Joined: Fri Apr 25, 2003 6:03 pm
Location: Lincoln, UK
Contact:

Post by Kale »

Heres a simple way that multiple values can be returned by a procedure:

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
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

:wink:
--Kale

Image
Intrigued
Enthusiast
Enthusiast
Posts: 501
Joined: Thu Jun 02, 2005 3:55 am
Location: U.S.A.

Post by Intrigued »

Thanks Kale, I'm goint to take off my dunce hat and practice with this code.

Thanks again.
Intrigued - Registered PureBasic, lifetime updates user
Intrigued
Enthusiast
Enthusiast
Posts: 501
Joined: Thu Jun 02, 2005 3:55 am
Location: U.S.A.

Post by Intrigued »

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:

Code: Select all

MessageRequester("", Str(@Coords))
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)

:x

:wink:
Intrigued - Registered PureBasic, lifetime updates user
Dare2
Moderator
Moderator
Posts: 3321
Joined: Sat Dec 27, 2003 3:55 am
Location: Great Southern Land

Post by Dare2 »

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.

Code: Select all

Structure myStuff
  myLong.l
  myDoubleWord.l
EndStructure

ProcedureDLL getMyStuff(*itIsMine.myStuff)
  *itIsMine\myLong=-1
  *itIsMine\myDoubleWord=1
EndProcedure
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:

Code: Select all

alsoMine.myStuff
getMyStuff(@alsoMine)
Debug alsoMine\myLong
Debug alsoMine\myDoubleWord
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 .. :)
@}--`--,-- A rose by any other name ..
Intrigued
Enthusiast
Enthusiast
Posts: 501
Joined: Thu Jun 02, 2005 3:55 am
Location: U.S.A.

Post by Intrigued »

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.

Code: Select all

Structure myStuff
  myLong.l
  myDoubleWord.l
EndStructure

ProcedureDLL getMyStuff(*itIsMine.myStuff)
  *itIsMine\myLong=-1
  *itIsMine\myDoubleWord=1
EndProcedure
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:

Code: Select all

alsoMine.myStuff
getMyStuff(@alsoMine)
Debug alsoMine\myLong
Debug alsoMine\myDoubleWord
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 .. :)
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.

So, I am using PB to help expand the other platform via .dlls is what I'm muttering on about.

:-D

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
Dare2
Moderator
Moderator
Posts: 3321
Joined: Sat Dec 27, 2003 3:55 am
Location: Great Southern Land

Post by Dare2 »

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!
@}--`--,-- A rose by any other name ..
Intrigued
Enthusiast
Enthusiast
Posts: 501
Joined: Thu Jun 02, 2005 3:55 am
Location: U.S.A.

Post by Intrigued »

Dare2 wrote: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 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" :D
Intrigued - Registered PureBasic, lifetime updates user
Dare2
Moderator
Moderator
Posts: 3321
Joined: Sat Dec 27, 2003 3:55 am
Location: Great Southern Land

Post by Dare2 »

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!
@}--`--,-- A rose by any other name ..
Intrigued
Enthusiast
Enthusiast
Posts: 501
Joined: Thu Jun 02, 2005 3:55 am
Location: U.S.A.

Post by Intrigued »

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!
Thanks again for your help. It's helped me look at the situation in a different light.

*thumbs up*
Intrigued - Registered PureBasic, lifetime updates user
FloHimself
Enthusiast
Enthusiast
Posts: 229
Joined: Wed May 14, 2003 3:38 pm
Location: Lüneburg - Germany

Post by FloHimself »

Intrigued 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...
Just discovered this thread and haven't read all... but sounds to me you
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
Post Reply