• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Documentation about extensions (external function) is inconsistent

S

syscall

Guest
Hell',

I've finally reached 5 posts, yay! (I can now post links.)
(Keep in mind I am still a noob in GameMaker tech.)
But, I have read a couple of docs pages around external functions and how they work via "extensions".
I would like to point out several minor inconsistencies which I have come across yesterday, in hope that somebody will correct them:
Description said:
Please note that for functions with 4 or more arguments, all of them must be of type ty_real.
"4 or more". OK. So, argCount >= 4: all arguments must be of type double.
Creating Extensions said:
NOTE: If you are creating a Windows dll file and it has more than four arguments, all arguments must be of the same type.
"more than 4". OK. So, argCount > 4: all arguments must be of the same type. Now all could be strings?!

Creating Functions said:
This is limited to a maximum of sixteen arguments, and note that for functions with 4 or more arguments, all of them must be of type double.
It states the same as the first bullet-point above ("4 or more"). It is inconsistent with the bullet-point "more than 4".
Creating Functions said:
Return Type - What the function returns. This can be either a string (text) or a double (real number).
It would be worth mentioning the following (where it is missing): if the function returns no value (void), then a return type you specify is ignored (it does not matter). As it is written on the page below:
Creating Extensions said:
you can define the return type, which can be a double (real number floating point value) or a string - if there is nothing returned by the external function then this does not matter
A couple of more things:
On external_define and external_call pages:
They only ever mention Windows (.dll) and Mac (.dylib), well what about Linux (.so) file? Is Linux (Ubuntu) not supported?!
Also, on both pages, they have mixed the maximum number of args allowed:
Syntax said:
argtype[10]
Argument column said:
argtype[0 ... 10]
Argument description column said:
Argument column said:
args[0...10]
I think it should be corrected like so: just replace occurrences of number 10 with 15.
Because, an external function is limited to a total of 16 arguments (not 11).
On related pages, add the missing information about return type: when function returns no value (void), then a type you specify is ignored (it does not matter). Also, maybe document what value would external_call return in that case?

I hope somebody will find 5 minutes to correct those inconsistencies. I'd correct them myself, but it seems like being a member of GMC doesn't let me do it.

Peace.

Best regards!
 
L

Lonewolff

Guest
I personally steer clear of external_call and external_define due to inconsistencies that bit me between Windows and Linux, back in the 1.4 days. Ever since then I have defined the functions in the extension editor and have never looked back. No idea if these inconsistencies still exist, as it doesn't affect me.

This also gives the huge advantage of being able to completely avoid scripts altogether when creating a DLL based extension. Scriptless extensions all the way! :D

All of my more recent extensions (created in the last four years or so) have been completely scriptless. The extensions behave as if you have extended GML itself.
 
S

syscall

Guest
Ever since then I have defined the functions in the extension editor and have never looked back.
Well. IMO, an extension editor could be improved, instead of throwing an error message when you accidentally enter a whitespace in the name textbox, how about restricting key input to the allowed format? (i.e. Regex validation: "^[A-Za-z_][0-9A-Za-z_]*$")
An external name textbox could be replaced with the combobox, and populate it with all exported functions' names (PE parse) instead of having a user to manually type out external names... (It is annoying.)
And many more improvements could be made.
(This is kind of very disappointing when I see the initial release of GameMaker was all the way back in year 1999.)
 
L

Lonewolff

Guest
I've never had the white space problem, because it's illegal to have spaces in function names anyway. So I have never tried.

I quite like the extension editor these days.
 
S

syscall

Guest
I've never had the white space problem, because it's illegal to have spaces in function names anyway. So I have never tried.
You never entered a space accidentally? xD

I quite like the extension editor these days.
Well, it doesn't even have warnings of any kind.
Say, you assign the same external name on 2 separate functions.
There are no errors/warnings at all. This is hilarious now, it feels like it were made by 5 year old kid.
 
Last edited by a moderator:

GMWolf

aka fel666
I actually quite dislikes the extension editor myself.
It's fine if you have maybe 5 functions in your extension. But when you have 20+ functions, its very clunky and time consuming.

Would much rather have a way to define it with text directly. Maybe a JSON alternative? Would be great.
 
S

syscall

Guest
Maybe a JSON alternative? Would be great.
Actually, I have spent my whole morning on exactly just that! (You read my mind.) LOL.
I am creating a CLI and GUI program to make it a whole lot easier (right now it suits my needs)...
Alrighty. I have been doing a bit of reverse engineering on GMS2 there too... Basically, if you go to your "<project>\extensions\<extension_name>" folder, open the (<extension_name>.yy) file using a text editor, you will see it is basically a JSON file.
In there you will find definitions of files, constants (macros), functions of the particular extension...
There's too much to tell on GM's "MVC format", I will just tell you a couple of things: create a sample extension in GMS2, and then open the .yy file and inspect the changes in JSON as you change/save them in GMS.

What I can tell you quickly about "GMExtension.GMExtensionFile.GMExtensionFunction" model: "args" field is an array of numbers, 1 represents a string while 2 represents a number type (same goes for the returnType field). Everything else is kind of self-explanatory.
I'm nearly completely done on implementing all of the (extension-related) models.

P.S.
I did notice a bug while working on my program, it is to do with the "date" field in the "GMExtension" model, the format is wrong, minute and month are swapped.
I don't know how to report bugs about GameMaker, if you could tell me, I would be glad to report the bug.
 
L

Lonewolff

Guest
You never entered a space accidentally? xD
Not that I recall. If I have, I would have immediately caught it as invalid input. Which it is.


Well, it doesn't even have warnings of any kind.
Say, you assign the same external name on 2 separate functions.
There are no errors/warnings at all. This is hilarious now, it feels like it were made by 5 year old kid.
This is valid operation though. So I don't understand the need of a warning.

If you are entering the wrong external function name, you have made an error.



Code:
a = 7 * 6;
"Arrrggh bloody GameMaker, keeps outputting 42 as the answer. I clearly meant to type 7 * 7. Why didn't it throw a warning?!?!"


I actually quite dislikes the extension editor myself.
It's fine if you have maybe 5 functions in your extension. But when you have 20+ functions, its very clunky and time consuming.
All comes back to preference. And that's the beauty of it. You can still use the external define functions and type 60 characters of text for each function. Or you can just populate a couple of boxes. It's up to you.

Now that we have local asset packages, it should be a once off thing anyway.
 
Last edited:
S

syscall

Guest
This is valid operation though. So I don't understand the need of a warning.
Oh. Yeah you are right... derp...
My bad there, I am sorry if it came out rude from me.
(It does throw an error if you use an already existing name; "name must be unique".)

However, here is the questionable case:
What if you use a name of already defined (builtin) GML function? (It doesn't throw an error in that case.)
Say you call it "abs", returning a double value, and taking in a double as the only argument. (Mimic the signature of the builtin abs function.)
upload_2019-7-7_1-55-43.png
What would GML use if you were to do
Code:
var my_num = -3.14;
if (is_real(my_num)) { show_message(string(abs(my_num))); }
?
I've just tested it out quickly, it turns out an external function is being called instead of the builtin GML function! I don't know if such behaviour is intentional or not, but the help text is wrong then:
upload_2019-7-7_2-0-5.png
(Also, if you press F1 while the caret is on the abs, it will open up docs about the builtin function. Which is wrong, since, the external function is actually being used. So, the help text from the extension should be used instead.)

How am I supposed to call the builtin "abs" function now?! xD
 
L

Lonewolff

Guest
How am I supposed to call the builtin "abs" function now?! xD
Again, to me this is a feature.

If the inbuilt GML function is inefficient or poorly written, you can override it with your own implementation. Like virtual functions in C++.

But once, you override there is no calling the initial implementation.
 
S

syscall

Guest
Again, to me this is a feature. If the inbuilt GML function is inefficient or poorly written, you can override it with your own implementation. Like virtual functions in C++.
Ok, that does make sense.

But once, you override there is no calling the initial implementation.
That. That's kind of a limitation then. And it appears to be undocumented.
 

rIKmAN

Member
That. That's kind of a limitation then.
What if you change the signature to have an extra argument than the builtin GML function?
Can you then use both depending on the arguments you pass into the function?

It kinda seems like you are making a problem where there really isn't one though, just prefix or suffix your own version of the function - problem solved.
 
L

Lonewolff

Guest
That. That's kind of a limitation then. And it appears to be undocumented.
Not seeing why.

Why do you need to override a function and then have access to the old function? Why override the function in the first place?

If you need both functions, just call one '*_ext' or something.

As @rIKmAN said, you are trying to create a solution for a problem that doesn't exist.
 

Mert

Member
Hey, extension maker here.

If you need to pass data between extension <> GML, try to use a single string instead of arguments. You can then parse it in the extension.
Other than that, Game Maker's extension system is horrible.
 
S

syscall

Guest
What if you change the signature to have an extra argument than the builtin GML function?
Can you then use both depending on the arguments you pass into the function?
I thought it would work in sense of overloading...
I made a quick test, but it turns it won't compile, because it is "number of arguments expected 1 got 2":
upload_2019-7-7_3-0-56.png
upload_2019-7-7_2-59-0.png

So, if your external function doesn't take the same amount of arguments as builtin function, you're unable to override (nor overload) builtin GML function.

Ok, to answer our question: no.
 
S

syscall

Guest
It kinda seems like you are making a problem where there really isn't one though, just prefix or suffix your own version of the function
Why do you need to override a function and then have access to the old function? Why override the function in the first place?

But, it has a potential problem of breaking code (since it is undocumented until figured and revealed, kind of what I do here). I didn't knew how GM extensions work, and apparently still doesn't know all the caveats (such as overriding one).
Say, you import a 3rd-party extension, it could be overriding some builtin GML function without you being aware of it!

If you need to pass data between extension <> GML, try to use a single string instead of arguments. You can then parse it in the extension.
Hi, I am not sure you're up with our topic here.
Perhaps you meant to post that in my other thread.
(Not sure how it reflects on the problem. The problem there is, I didn't know you can't pass data back to GML context yet. I am in the process of nailing it down using an array or buffer. As soon as I figure it out, I will post about it in that thread.)
 

rIKmAN

Member
Say, you import a 3rd-party extension, it could be overriding some builtin GML function without you being aware of it!
That's why it's standard practice for extension writers to prefix or suffix their function names so as not to clash with any built in functions and cause problems for people who might use it in their projects.

I'm not sure if that's documented in the manual as I never looked it up - it seems like common sense to me.

Your username is perfect for a prefix: syscall_abs(), syscall_draw_text(), syscall_draw_sprite() etc.
If that's too much typing: sc_abs(), sc_draw_text(), sc_draw_sprite().
 
L

Lonewolff

Guest
Agreed. It's just common sense to prefix your function names.

And yes, there is nothing to stop an extension writer from overriding the functions without you knowing it. (Well, you would know if you opened up their extension)

Also, nothing stopping an extension writer from deleting all of your data from your hard disk either.

Comes back to how well you trust your extension writer. No different from any other exe that you download from the internet really.
 
L

Lonewolff

Guest
Hey, extension maker here.

If you need to pass data between extension <> GML, try to use a single string instead of arguments. You can then parse it in the extension.
Other than that, Game Maker's extension system is horrible.
Eeek, not how I'd do it. Nasty!
 
S

syscall

Guest
It's just common sense to prefix your function names.
I could agree as well, it is simply common sense.
But... Is it really okay? There is no warning (in IDE or docs) when importing an extension from file (not marketplace).
(No anti-virus will ever find a malicious code in such file, since it is not executable code.)
 
L

Lonewolff

Guest
I could agree as well, it is simply common sense.
But... Is it really okay? There is no warning (in IDE or docs) when importing an extension from file (not marketplace).
(No anti-virus will ever find a malicious code in such file, since it is not executable code.)
A DLL is basically an executable with no entry point. A virus checker will flag DLL's if they are deemed suspicious.
 
S

syscall

Guest
A DLL is basically an executable with no entry point. A virus checker will flag DLL's if they are deemed suspicious.
I was talking importing an extension from a file, the ".gmez" file format (I haven't reversed engineered this format yet, so I don't know in what form would executable file such as DLL be read as).
 

Mert

Member
Eeek, not how I'd do it. Nasty!
I'm actually writing a discord bot based-game maker game(well it's going to be one of those free extensions). The main player is controlled by discord users.
What am I doing, just passing JSON string around.
Am definitely doin' thaaaat :)

(I'm probably doing things terribly)
 
L

Lonewolff

Guest
I was talking importing an extension from a file, the ".gmez" file format (I haven't reversed engineered this format yet, so I don't know in what form would executable file such as DLL be read as).
It doesn't read a DLL. It interfaces with it. GM has no knowledge of what the DLL does.
 
S

Sam (Deleted User)

Guest
I was talking importing an extension from a file, the ".gmez" file format (I haven't reversed engineered this format yet, so I don't know in what form would executable file such as DLL be read as).
gmez is a standard 7zip archive with pure xml inside. No reverse-engineering necessary. :D
 
Top