Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

DarkBASIC Professional Discussion / Using variables from included files not working.

Author
Message
i lyke pineconez
13
Years of Service
User Offline
Joined: 16th Aug 2010
Location:
Posted: 12th Jan 2011 06:23
Probably a noob Question, I have included a file in my main program, but whenever I go to use one of the variables assigned in the included file for anything, it acts like its not there. I have tried puting Global in front of it, and I have called the function that assigns it, i know that the variable has a value, im just wondering how i can get my main file to see it? This number is going to change often, and i need my included file to be able to change it. I can post the code if anyone needs it.
enderleit
16
Years of Service
User Offline
Joined: 30th May 2007
Location: Denmark
Posted: 12th Jan 2011 07:28
Your declarations and assignments needs to be inside a function, and you need to call that function before using it, as far as I know...

Something like this:



This is how I do it anyways.
Then you just call InitVariables() before you start using the variables. Notice how constants can be declared outside functions without any problems.

If I'm wrong, please correct me. But I know this atleast works.

Phaelax
DBPro Master
21
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 12th Jan 2011 13:20
The variables need to exist in your main file, not the included file. When your program is compiled, included files are appended to the end of your main file to create one giant source file, so to speak.

"Only the educated are free" ~Epictetus
"Imagination is more important than knowledge..." ~Einstein
IanM
Retired Moderator
21
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 12th Jan 2011 14:15
Not true, enterleit has it right.

Variable and arrays can be defined as global anywhere in your code, but won't get initialised to anything other than zero (or blank strings or undefined arrays) until the flow of execution runs through them.

Alfa x
17
Years of Service
User Offline
Joined: 1st Jul 2006
Location: Colombia
Posted: 12th Jan 2011 14:18 Edited at: 12th Jan 2011 14:19
Thats true,
I had the same problem and solution as enderleit and IAnM said long ago.
sladeiw
14
Years of Service
User Offline
Joined: 16th May 2009
Location: UK
Posted: 12th Jan 2011 14:21 Edited at: 12th Jan 2011 14:22
Quote: "The variables need to exist in your main file, not the included file. When your program is compiled, included files are appended to the end of your main file to create one giant source file, so to speak."


True regarding include files appening, but the example from enderleit works, and can be within an `include` file. The only minor additions would be:
You don't need to declare arrays as globals because they always are.
You can shorten variable declarations using `global myInteger as integer=0`
Integer array elements default to 0 so no need to explicitly set them.

The theory is sound though.

edit: Bah beaten by multiple people
IanM
Retired Moderator
21
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 12th Jan 2011 18:54
Regarding declaring arrays as global - that's entirely correct, however at one point it was not true. Now, entirely out of habit, I still declare my arrays (and my other variables) as global or local.

KISTech
16
Years of Service
User Offline
Joined: 8th Feb 2008
Location: Aloha, Oregon
Posted: 12th Jan 2011 22:34
I place all my variables and arrays in a separate file that's part of the project, and place them in a subroutine.

Then at the top of the main source I put,

gosub Vars
gosub Arrays

Phaelax
DBPro Master
21
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 13th Jan 2011 09:58
What about UDT's? Can those be declared inside a function?

"Only the educated are free" ~Epictetus
"Imagination is more important than knowledge..." ~Einstein
=PRoF=
21
Years of Service
User Offline
Joined: 17th Mar 2003
Location: Milton Keynes, UK
Posted: 13th Jan 2011 10:04
@Phaelax:
No, to the best of my knowledge you can't declare a UDT inside a function.

Frank C
13
Years of Service
User Offline
Joined: 3rd Jul 2010
Location: Houston TX
Posted: 13th Jan 2011 13:51
I have a Globals.dba file that I use as the main file and ensure that the next file loaded is where my main loop is, this allows me to keep all UDT's, constants, and global variables in one file and everything is initialized at the beginning. I still use local variables in their functions as needed.
i lyke pineconez
13
Years of Service
User Offline
Joined: 16th Aug 2010
Location:
Posted: 15th Jan 2011 05:28 Edited at: 15th Jan 2011 05:34
Sorry for getting back so late, I havent had time to check this forum recently. I'll look over your posts in more detail in a minute. Thanks for responding!

EDIT: I do beleive my variables are already in a function, thats why im stumped. I am using Evolveds water shader, and im trying to use the WaterHeight# variable from the MakeWater function, which has already been called, but for some reason it isnt working.
KISTech
16
Years of Service
User Offline
Joined: 8th Feb 2008
Location: Aloha, Oregon
Posted: 15th Jan 2011 18:39 Edited at: 15th Jan 2011 20:31
Quote: " I do beleive my variables are already in a function, thats why im stumped."

The thing to take away from this thread so far is that your variable declarations should never be inside a function, unless they are local variables that are only used inside that function. Any variable you declare inside a function will no longer exist after you exit that function.

The old standard programming practice is to put ALL your variable declarations at the TOP of the program so they are executed before any other code.

Some of us (probably most) have placed all of our variable declarations into a Subroutine (not the same as a function) and then executed that subroutine at the top of the main program.

So you might have a file called Variables.dba that contains..



Vars:
global a as integer
global b as integer
global c$ as string
Return



Then at the top of your main program file put..



gosub Vars



The above is supposed to be inside CODE tags, but isn't working for some reason..

IanM
Retired Moderator
21
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 15th Jan 2011 19:21
Global variables and global arrays can be declared ANYWHERE, including within functions and in sections of code that never get executed.

However, the only problem with doing this is that they will never get initialised.

It is useful therefore to have a subroutine or a function that will carry out this initialisation for you. (Link to a recent post of mine that describes and implements this). Note that if your variables are numeric and need to be initialised to zero, or if they are strings that are initialised to empty strings, then you don't need to initialise the variables, and therefore don't need a subroutine or function to initialise them.

This allows you to modularise your code (using separate included files containing connected functionality), and to also keep the variables used by that code within the same file.

If I've missed anything, let me know, but that's pretty much a definitive explanation of the subject.

KISTech
16
Years of Service
User Offline
Joined: 8th Feb 2008
Location: Aloha, Oregon
Posted: 15th Jan 2011 20:29 Edited at: 15th Jan 2011 20:30
Fair enough. You "can" initialize globals inside a function, but it's never been a recommended practice.

sladeiw
14
Years of Service
User Offline
Joined: 16th May 2009
Location: UK
Posted: 15th Jan 2011 23:01
All of this would be much simpler if the compiler inserted `includes` at the position of the actual include statement.

Would an extension to the include command, something like `include here` be feasible/easy?
IanM
Retired Moderator
21
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 16th Jan 2011 00:10
Quote: "but it's never been a recommended practice"

Ok, as soon as you tell me what the recommended practice is, who recommended it, and what their justification was, I'll consider it

@sladeiw,
There's plug-in functionality built into the editor, but whether you can pre-process with it, and how you would do it if you could is something that has never been made clear.

sladeiw
14
Years of Service
User Offline
Joined: 16th May 2009
Location: UK
Posted: 16th Jan 2011 13:26
Quote: "here's plug-in functionality built into the editor"


I've never even noticed those before, but I can't find any info on how to use them on the forum. Has anybody ever written one?
KISTech
16
Years of Service
User Offline
Joined: 8th Feb 2008
Location: Aloha, Oregon
Posted: 16th Jan 2011 20:10
Quote: "Ok, as soon as you tell me what the recommended practice is, who recommended it, and what their justification was, "


It's been a little while, but the simple answer is..

The recommended practice:
To always put your variables at the top of the program, and that they be executed first before anything else.

Who recommended it:
Every instructor I've had since 1983 teaching AppleSoft BASIC, 6502 Assembler, COBOL, and IBM 370 Assembler.

The justification:
Two main reasons. 1. So that anyone else that came along that had to maintain your code could easily find all the variables and structures and didn't have to go searching for them interspersed in the code. 2. So the compiler had all the information it needed about the variables and structures before processing the code. (I guess some of the older compilers weren't smart enough to continue to look for variables past the beginning of the program code, or they just simply wrote them that way because everyone was told to put their variables first.)


I'm not saying what you propose is right or wrong, hell I had instructors that would yell at me for putting my variables in a subroutine. I'm just passing on a recommendation that's been given to me many times over the years, and it seems to work fairly well. Of course I also understand that times change, compilers get smarter, and different techniques are taught. I haven't been in a programming class for nearly 20 years, so you might say these recommendations are the "old way" of doing things.

Either way, you are the last person I'm going to argue with about programming. Your skills and knowledge are far beyond mine, and I would lose the argument every time.

IanM
Retired Moderator
21
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 16th Jan 2011 23:42 Edited at: 16th Jan 2011 23:44
Ok, for COBOL and assembly languages, you are quite right - for COBOL it has to be that way, and mixing variables into the code for assembly is simply ugly. I don't know anything about Applesoft Basic, so I'll give you the benefit of the doubt there too

However, you should take that advice and attempt to generalise it to multi-file and modular systems such as DBPro allows you (although DBPro isn't truly modular).

Modularisation is used to keep related functionality in one place (such as input routines for example) - it's also used for data hiding (but this is the bit DBPro can't do). This includes not only functions and subroutines, but also the variables that they operate upon. Doing so allows you to reuse the module in another project simply by taking that 1 file across to the new project.

If you keep your variables in different files from the code that operates on them, then to do this you have to hunt for its variables, identify all of them properly, and then copy/paste them into the top of your new main file, hoping you haven't missed any.

IMO, putting it all in one file makes it all simpler - not that it'll work for everyone though, as the majority of people I see who 'appear' to modularise in DBPro, tend to access the variables and arrays directly instead of via functions - that's why they also have problems with types too (and declare these at the top of their main code) as the definitions are very sensitive in their placement in the code - you can have problems accessing a typed variable if the variable is accessed before the type definition appears.

The sequence I use for a module is like so:
1. Type definitions.
2. Variable and array definitions.
3. Initialisation function (or subroutine).
4. Other functions (or subroutines) for the module.

All access to anything within the module is via a function, even reading a value from a simple integer - you may want to change that integer later to something else (eg an array if you need to hold multiple values), but if you access the variable directly, you have to change code throughout your system, not just the module.

I treat the main file also as just another module, although technically, using my definition, it doesn't need to be.

Ok, that's enough preaching for now

i lyke pineconez
13
Years of Service
User Offline
Joined: 16th Aug 2010
Location:
Posted: 18th Jan 2011 18:51
Sorry for getting back to you guys so late again, also sorry if this has been frustrating for you . I'm noob so I dont get most this stuff right away. I'm pretty sure I have the hang of it now. Thanks for all your help!
Mobiius
Valued Member
21
Years of Service
User Offline
Joined: 27th Feb 2003
Location: The Cold North
Posted: 18th Jan 2011 19:26 Edited at: 18th Jan 2011 19:28
When defining variables in functions, (for example setting up a shader) I generally include in the function which sets the shader to an object, a simple check to see (for example) if the ShaderNo variable has anything in it?

If it does, assume that the system has been initialised and move to the next bit. If it's empty, then call the initialisation function. In this function, I then initialise every variable this shader needs to work.

I'm using this method in my game engine, and it's allowed my to take several seperate code examples, written my several people who were not collaborating, and add them "drag and drop" into my engine. (Once I converted each code snippet to match my conventions)

Now, I (currently) have about 10 dba files, each performing a separate and distinct set of functions related to only 1 task. If there's anything I can't initialise from within a function, I include (in a remstart/remend block) the entire variable initialisation code needed ready to be paste at the top of the main code file.

I find this to be the best way of ensuring that each module can be swapped into any program I'm writing without any further work needed. (I even managed to drag and drop a UI/scripting engine into the game engine by simply adding the .dba file to the project, and it worked 1st time.

It might not be the way anyone else does it, but I'll be damned if I can find a better way of creating modular code in DBP than this!

I'll include a sample dba file so you can see how easy it is to add/remove functionality to programs using this method.

My signature is NOT a moderator plaything! Stop changing it!

Attachments

Login to view attachments
Green Gandalf
VIP Member
19
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 21st Jan 2011 00:46
@IanM

Just seen your posts on this thread.

I'm a bit confused by your latest post.

Suppose I've got one module, module1 say, which loads and processes a heightmap image. The heightmap dimensions, for example, might be stored in globals and the values stored in an array so they could be used by another module, module2. In this example, you could declare the globals in a third module, module0. So the calling program could define the globals by calling module0, then initialise them by calling module1, then do something interesting with the globals in module2.

However, your latest post seems to suggest everything should be in one file (or module?) which seems to defeat the object. If variables and arrays are used by several modules you can't have the variables declared more then once unless they are passed as parameters to functions. Perhaps I've misunderstood something here?

I feel I've missed the essence of what you're suggesting. Your description of "module" sounds very similar to what I regard as a "program" and doesn't seem to help much.
enderleit
16
Years of Service
User Offline
Joined: 30th May 2007
Location: Denmark
Posted: 21st Jan 2011 03:19 Edited at: 21st Jan 2011 03:21
I usually do it the way IanM suggests.
Even though DBPro isn't actually an Object Oriented Programming languange, I find it much easier to re-use code if you keep it modular.

In your case GG, it might be structured something like this:



1. This "module" is self contained and could easily be included in another project.

2. You can get width/height info by calling "member" functions of the Module. (would most likely have been a class in C++)

3. The internal data/arrays of the module is protected by using the member functions to access the module.

4. You only really need to know the Interface functions to be able to use the module.

Hope this helped.

Green Gandalf
VIP Member
19
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 21st Jan 2011 13:42
Quote: "Hope this helped."


It did thanks. Just what I needed.

I've copied that snippet into my templates folder for future reference.
IanM
Retired Moderator
21
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 21st Jan 2011 20:25
Just to confirm, that's exactly what I meant.

I also use various conventions to keep things private, safe and easier to maintain (although I sometimes skip some of these depending on whim):
- constants have a prefix specific to the module.
- constants are placed as if they were variables, the exception being that if there are a lot of them, I put then at the end of the module, after all of the code.
- if a function has 2 leading underscores, it should only be called by code within the module.
- all type definitions end with _t, to allow related names to be used for variables.
- all module-level variables are stored within a type'd variable, both for safety, and to avoid polluting the global namespace.

I've also toyed with InitialiseXXX and ShutdownXXX functions, that if named with those specific prefixes, automatically get called at program start and end. All that has to happen for this to occur is that you add the module to the program (TBH, it's still in the 'toy' stage, as I'm not really too keen on the fact that the execution of the code is not obvious from reading the program).

Anyway, there are a few more nuggets you can dig through to see if any are gold.

Green Gandalf
VIP Member
19
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 21st Jan 2011 20:46
For the record, I've already started implementing your (i.e. IanM + enderleit's) suggestions into my current project and it is coming along nicely. The code looks cleaner too.

So thanks to both of you for a necessary lesson.
enderleit
16
Years of Service
User Offline
Joined: 30th May 2007
Location: Denmark
Posted: 21st Jan 2011 23:52
You're welcome GG, and anyone else...

IanM:
Quote: "- constants have a prefix specific to the module."

I actually do this also, just forgot in this quick snippet.

Quote: "- if a function has 2 leading underscores, it should only be called by code within the module."

This is actually a good idea aswell... To signify that this is an internal function. Going to start using that aswell.

Quote: "- all module-level variables are stored within a type'd variable, both for safety, and to avoid polluting the global namespace."

Does this have any speed/memory benefits? I mean the part about not polluting the global namespace... And could you show a snippet of how you do this exactly?

IanM
Retired Moderator
21
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 22nd Jan 2011 00:16
No speed benefits, no memory benefits. It's basically just the work-around suggested when we asked for explicit variable declarations years ago:


If you mistype a variable name, because it is part of the type, then you'll get an error.

It also helps that you don't have to think of lots of different variations on variable name, although that's not really a problem as you can also prefix those like I do for constants.

enderleit
16
Years of Service
User Offline
Joined: 30th May 2007
Location: Denmark
Posted: 22nd Jan 2011 12:10
Quote: "although that's not really a problem as you can also prefix those like I do for constants"

Yeah, that's what I usually do nowadays...

For example my System module contains the mouse info:


Login to post a reply

Server time is: 2024-04-28 10:04:18
Your offset time is: 2024-04-28 10:04:18