New feature: #import directive

Plombo

OpenBOR Developer
Staff member
Those of you who were around 2 years ago might have some recollection of me working on a new script feature called "#import" that never got finished.  Well, as of a few minutes ago, it's finished and working in SVN now! :D

What is #import?
#import is a new script feature that eliminates the need to use #include to use functions from another script file.  #include is nice, of course, but when one file of utility functions is included in 20 different script files, the code for those utility functions is stored in memory 20 times instead of once.  On the other hand, no matter how many times it is imported using #import, it will only be compiled and stored in memory once.  So #import is a huge memory-saver for mods that heavily utilize #include.

How do I use #import?
The syntax for #import is identical to that of #include.  Somewhere in your script file (at the top is the most logical place), add a line like this for each file you want to import:
Code:
#import data/scripts/foo.c

It does not matter where in the file the #import line is, but putting all of your imports above all of your actual code makes your file more readable, and makes it easier to keep track of what's being imported in each file.

A point of possible interest for C/C++ programmers and no one else:
Just like the #include directive in OpenBOR, and unlike the #include directive in C/C++, you have to use the full path from the data folder; there's no relative include/import path.  So if you want to import foo.c from bar.c, even if both files are in data/scripts, you still have to import "data/scripts/foo.c"; you can't shorten it to just "foo.c".  This shouldn't be a source of confusion for anyone except programmers familiar with C/C++, and even then, #include in OpenBOR has worked this way for years, so everyone should be used to it already.

What is the difference between #import and #include?
Including a file at a certain point in your script can be thought of as what you would get if you copied and pasted the contents of that file into the script at that point.  All of the functions, variables, and preprocessor directives in the included file are replicated in the script including it.

Importing a file, on the other hand, simply keeps a list of the functions in the imported file, and allows those functions to be called from the script doing the importing.  Nothing else.  Any variables and preprocessor macros defined in the imported script will not be available from the importing script, and vice versa.  Variables and preprocessor macros are local to the file they are defined in.  If you want to import a file to use its variables or preprocessor macros, you should be using #include instead.

The last important thing to mention here is that as mentioned above, a script that is imported from more than one different script will share one instance across all of the scripts importing it.  A side effect of this is that variables declared at global scope (i.e., declared outside of a function) will be shared as well.  This is different from what you get if you do the same thing with #include, in which case the engine will create a unique instance of those global variables for each place the file is included.

Does importing work recursively?
No.  If a script foo.c imports a script bar.c, and bar.c imports another script baz.c, the functions of baz.c will not be available in foo.c.  You'll have to directly import both bar.c and baz.c in foo.c if you want to use functions from both.

What if I import 2 files and they have a function with the same name?
If that's the case, you really should rename one of the functions, but if you don't, the engine will use the function from whichever script was imported last.  Locally declared functions also take priority over imported ones - to use the previous example, if foo.c and bar.c both have a function called "reset()", calling reset from foo.c will always use its own version and not the one in bar.c.

Is this the same as the #import directive in GCC?
No.  No no no no no.  It's completely different, even if it shares the same name and similar syntax.  I won't explain the differences here because they are obvious if you read the GCC documentation and compare it to this. ;)

When should I use #import as opposed to #include?
As a general rule, it is best to import files containing code and include files containing macros.  This means you should separate macros and code into separate files if you want to include/import both into other script files.

I'm using #import like you described, but I get an error and/or crash!
It's a new feature and hasn't gotten much testing, so if you encounter what you think is a bug, please report it by replying to this thread!
 
Nice addition.

Let me guess, we can finally say bye-bye to those duplicate huge scripts like in, for example, Mix Master?
8)
 
utunnels said:
Nice addition.

Let me guess, we can finally say bye-bye to those duplicate huge scripts like in, for example, Mix Master?
8)

Yeah.  I would test the memory savings myself if the current MixMasters download weren't a broken archive.
 
Nice. Great work Plombo. Gonna download latest openBor and update my mods to use this from now on
 
MatMan said:
Nice. Great work Plombo. Gonna download latest openBor and update my mods to use this from now on

Good to hear.  Would you mind tracking the difference in memory usage between from using #import?  I'm curious to know how much it saves in a practical application. :)
 
I've been an include junkie from day 1; every single one of my functions is broken down into its own file and included as needed (which tends to mean a LOT of includes). I've also made extensive use of your pre-processor, so this looks VERY interesting to me. Will check it out ASAP. Great work as always sir!

Looking forward to the day you get OOP support going.  ;)

DC
 
Damon Caskey said:
I've been an include junkie from day 1; every single one of my functions is broken down into its own file and included as needed (which tends to mean a LOT of includes). I've also made extensive use of your pre-processor, so this looks VERY interesting to me. Will check it out ASAP. Great work as always sir!

Having seen the number of #includes you use firsthand a couple of years ago, I'm even more interested to hear your memory savings from using #import. :)

Damon Caskey said:
Looking forward to the day you get OOP support going.  ;)

Haha, I wish. ;)

...I should ask SX again to send me the LavaLit smilies so we can have the animated "laughing" smiley back.
 
Plombo said:
Having seen the number of #includes you use firsthand a couple of years ago, I'm even more interested to hear your memory savings from using #import. :)

Wow. Just wow. It took a while to get everything all lined out but man was it worth it!  Using my Golden Axe Hackjob project I got the following results:

#include: 111MB
#import: 35MB

:o

Not surprising at all, but still amazing. I might add these results would be even more mind blowing, but currently I am only loading around ten models for testing. As more models are brought online, the savings would be increasingly exponential. This is a must use for scripted modules.

DC




[attachment deleted by admin]
 
I've started using the import command and alas, it didn't save as much memory for me (only a couple of bytes) but I don't really use the include to much as I have one huge .c file but it does seem to work and I'v noticed no problems using the new feature.

Once again, thanx Plombo.
 
Back
Top Bottom