get_function_address('function_name')

S

Sam (Deleted User)

Guest
Edit: Anyone else want this feature? YoYo responded to my ticket saying they would consider it in a future release if enough people on the GMC wanted it! :D (Original topic contents below, but the discussion has changed to requesting this function).

Anyone know what this function from GM 8.1 does? I'm not really clear on this. Not very well documented.
get_function_address('function_name') Returns the address of a GameMaker function. This can be passed to DLL's so the can call directly into GameMaker.
This feature is unsuported, so care must be taken when using this function.
Please Note: These functions use Delphi 2010 PASCAL calling convention and string formats.
That quote was taken from the bottom of this webpage: http://gamemaker.info/en/manual/414_00_dlls

It sounds like something that could be really really useful for extension writers if YoYo brought the function back in GameMaker Studio. I have a couple guesses as to what it does, but it's still a little confusing to me...

Is it basically a way to call a function from a string?

I tried this in 8.1 but nothing happened, (it returns -1):
Code:
get_function_address('show_message("poop")')
So I tried getting the return value with this, (using just 'show_message'):
Code:
get_string("",string(get_function_address('show_message')));
And it outputted in the textbox this:
Code:
6567176
So that's the address, I guess... Not sure what I do with it?

Thanks!
Samuel
 
Last edited by a moderator:

Tthecreator

Your Creator!
In the first example I guess you were looking for the stack frame of the function being called in the ''.
Yea it doesn't quite work that way.
Well when you load a game, every instruction needed is put into ram, including every game maker function.
So it gives you that address, which is a very general address and doesn't change depending on how much or how you run the function.

In cpp you could probably do something like

void (*foo)(int);
foo = &theAdressAsGivenByGM

//now just call it:
foo(3);

You might also need to do some weird double to address conversion schemes.

I hope that clarifies things. This would indeed be useful in gamemaker but I'm not sure whether the yoyo guys will actually take the time implementing this. I'd still love to see it though.
 
S

Sam (Deleted User)

Guest
Ah, I gotcha. That makes sense. I'll play around with the casting if the example you gave as a base doesn't work. It would be super cool if they at least made it work on Windows, if nothing else, since that's what legacy GM ran on. (I don't know if GM4Mac had this function, probably not...)

Thank you! :D

(I think I'll make a helpdesk ticket requesting this feature).

Edit:

Ticket submitted.
 
Last edited by a moderator:
S

Sam (Deleted User)

Guest
Anyone else want this feature? YoYo responded to my ticket saying they would consider it in a future release if enough people on the GMC wanted it! :D
 

FrostyCat

Redemption Seeker
Anyone else want this feature? YoYo responded to my ticket saying they would consider it in a future release if enough people on the GMC wanted it! :D
I would love to see this feature or a comparable equivalent. Imagine what would happen if we allow extensions direct access to:
  • Data structures: Extensions would then be able to take full data structure models as input and directly process them.
  • File functions: Extensions would then be able to get at files within the sandbox, which on some exports are virtual (e.g. Android, HTML5).
  • Buffers: Wouldn't be useful in native, but could still useful in HTML5 where pointers don't exist.
  • Surfaces: Computationally heavy graphics code can be delegated to native code without forcing the output to come out on top of everything else within GM.
These are just the more obvious ones I could think of at the moment. Experienced extension developers may already be able to access these via a side channel, but a formally documented mechanism would be best for forward compatibility.

GM7 and GM8 had a vibrant extension dev community following the publication of GMAPI. When 8.1 broke it with the new C++ runner, it completely died down. This history lesson alone is enough rationale to bring back similar functionality and also review the extensibility of GMS 2 as a whole.

This isn't the first time I've asked for this. And if YoYo doesn't act, probably also not the last.
 
S

Sam (Deleted User)

Guest
When 8.1 broke it with the new C++ runner, it completely died down.
I agree with your entire post. however I feel pretty certain the C++ runner wasn't introduced until GM:Studio 1.x came along, shortly after the discontinuing of GM:HTML5. I think something else in 8.1 must've broke the GMAPI. Though I could remember wrong.
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
IIRC GMAPI relied on having hardcoded offsets to some functions and internal structures so the effort of updating it whenever a GM update came out was substantial and the author had given up when GM8.1 started to get subsequent updates.

function_get_address is an interesting thing to consider, although also oddish.
Desktop platforms still have function addresses, though you'd have to match call convention and expected data (which prompts for more functions like getting pointers to instances).
Android requires you to dance around JNI because you can't do anything with a C++ function address in Java.
HTML5 would need to have a 1500 item lookup map (for function name -> function reference) inserted if the function is used.
Things that result in VM state transition (like script_execute or event_perform) would likely require changes to VM (as you'd be interrupting it amid a DLL call to do something else entirely).
 

GMWolf

aka fel666
Oh such functionality would be incredible!
GML could finally be used a scripting frontend for all kinds of DLLs!
What would be nifty is access to the renderer from DLL's too, without having GML in the middle, and without all the context manipulating bs. Just calling functions like draw_sprite from the DLL would be incredible! (GM would essentially become a C++ engine xD)
 
S

Sam (Deleted User)

Guest
The more people who comment in this topic and/or communicate to YoYo they want this feature, one way or another, the better. Allow me to tag some people for more input on the matter.

@Ghost in the IDE @Nocturne @zbox if anyone is aware of any other major extension writers who would potentially like this idea, please tag them! YoYo is watching this topic for Pete's sake!! :D
 

zbox

Member
GMC Elder
IIRC GMAPI relied on having hardcoded offsets to some functions and internal structures so the effort of updating it whenever a GM update came out was substantial and the author had given up when GM8.1 started to get subsequent updates.

function_get_address is an interesting thing to consider, although also oddish.
Desktop platforms still have function addresses, though you'd have to match call convention and expected data (which prompts for more functions like getting pointers to instances).
Android requires you to dance around JNI because you can't do anything with a C++ function address in Java.
HTML5 would need to have a 1500 item lookup map (for function name -> function reference) inserted if the function is used.
Things that result in VM state transition (like script_execute or event_perform) would likely require changes to VM (as you'd be interrupting it amid a DLL call to do something else entirely).
Definitely interested in this. Concerned at some of YA's points about practicality though
 
S

Sam (Deleted User)

Guest
@zbox Well, they did say if enough people wanted it they would consider, so it must be do-able enough that they would at least be willing. But yeah, it doesn't sound like it would be very easy to implement on non-desktop platforms.
 

rwkay

GameMaker Staff
GameMaker Dev.
OK this is not going to happen in the immediate future because of upcoming roadmap changes for method variables.... but the good news is that method variables are coming which could simplify what you are looking to do...

I will consider the implications of this change for extensions, but I think what you are actually asking for is the ability to call a GML function from an extension... now this has lots of issues (mainly to do with context of the call...) but within limits it is possible to do, within a constructed context...

This has similar issues with the Java JNI and you can read countless articles on how horrible that can get... I don't want to paint ourselves into a corner here...

Russell
 

GMWolf

aka fel666
but the good news is that method variables are coming which could simplify what you are looking to do...
ooooh, is that already in the works?

I will consider the implications of this change for extensions, but I think what you are actually asking for is the ability to call a GML function from an extension... now this has lots of issues (mainly to do with context of the call...) but within limits it is possible to do, within a constructed context...
At the very least, it would be nice to call "pure" functions.

As an extra feature, Exposing the renderer to extensions would be very nice too :)
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
As an extra feature, Exposing the renderer to extensions would be very nice too :)
You can use window_device to get a DirectX/OpenGL/... pointer to the rendering device and do what you please with it, though it is a little more DIY than calling draw_sprite directly from a DLL.
 

GMWolf

aka fel666
You can use window_device to get a DirectX/OpenGL/... pointer to the rendering device and do what you please with it, though it is a little more DIY than calling draw_sprite directly from a DLL.
yeah, I know you can do that, but then why am i using GM?
I would love to have access to GM's rendering engine, without having to deal with GML's shortcomings sometimes.
It really is a shame to have such a great engine, with a language like GML to interface with it.
 

rwkay

GameMaker Staff
GameMaker Dev.
We have no plans to expose the internal rendering functions for extensions, we have talked about it internally but we do not have the resources to do this at this time

Russell
 
S

Sam (Deleted User)

Guest
This could be used in my Microsoft Script Control extension to make a fully functional GML interpreter, with strict syntax checking. (an error will close the game if the strict syntax is incorrect or if there is a missing semicolon, etc.) Since JScript and GML have nearly identical syntax, I could use that as the base for my GML interpreter, and you could combine your JScript or VBScript with GML function calls. It would be less popular because the syntax is much different in VBScript than JScript, but you could easily write your interpreted GML with VBScript syntax as well.
 
L

Lonewolff

Guest
You can use window_device to get a DirectX/OpenGL/... pointer to the rendering device and do what you please with it, though it is a little more DIY than calling draw_sprite directly from a DLL.
Not exactly.

They changed the way the renderer handles the scenegraph in 2.x. It doesn't play as nicely as it did in 1.4.

Rendering a simple quad is quite a turd now.

I can elaborate if anyone is really interested.

And as a side note windw_device() won't return the address of the OpenGL renderer, it is a Windows only function.
 

rwkay

GameMaker Staff
GameMaker Dev.
on OpenGL there is a global context you don't need to get the handle in the same way so it is not needed..

We changed to DX11 for rendering in GMS2 on Windows in some ways this is easier (than DX9) in others it is more difficult - plenty of examples out there to show you how to do things though - if you are using an extension to draw a quad then you are doing it wrong... most of your rendering needs can be handled with vertex buffers and freezing them or calling an extension function to build a buffer and convert it to a vertex buffer in GML code.

Russell
 
L

Lonewolff

Guest
LOL @rwkay - how else would you render fully interactive vdeo inside GMS, Russ? ;)

You guys haven't managed it yet :D
 

rwkay

GameMaker Staff
GameMaker Dev.
not sure what you are meaning at all?????

We have plenty examples of rendering full 3D interactively without any extension required.

Russell
 
L

Lonewolff

Guest
I understand this. I was the first person on the planet to bring Video to the renderer, having it behave exactly as a sprite, preserving depth, and any other things you want to throw at it.

That starts out with a simple quad.

I am saying that the changes in GMS2 is much more difficult due to the way you have changed the scene graph.
 

rwkay

GameMaker Staff
GameMaker Dev.
But you see that is the ironic thing.... we did not change the scene graph... the layer system was always effectively there... just much more CPU intensive before.. the scene graph is exactly the same... so confused what has made it more complicated for you (apart from being DX11)

Russell
 
L

Lonewolff

Guest
Ok I'll explain in case you are not aware of what is currently happening.

Pseudo code

Code:
// What we want to happen

set_shader(something)
draw_sprite()
draw_quad_dll()
draw_sprite()
shader_reset()
Vs

Code:
// What now happens in GMS2 verifiable using Pix or VS Graphical debugger

set_shader(something)
draw_sprite()
draw_sprite()
shader_reset()

draw_quad_dll()
In GMS1.4 the first code example would stay true. But in GMS2 the call to the DLL is pushed out of order to after the shader_reset() call.

Which has all sorts of implications. Draw order is now incorrect when using painters algorithm and the quad no longer gets the benefits of the shader, meaning you have to have a precompiled HLSL shader inside the DLL.

Doesn't matter where you make the call to the DLL, it could be before any Sprite draw call, it will get pushed to the end.

As I said, makes it a turd to do anything now.

I can make a simple project and send to you if you want to see this for yourself.
 

rwkay

GameMaker Staff
GameMaker Dev.
I suspect that the issue you are seeing is because you have not informed us that you have changed state in the middle there... and the second draw_sprite() is not breaking the batch... just add in a draw_flush() - https://docs2.yoyogames.com/source/_build/3_scripting/4_gml_reference/drawing/draw_flush.html before the draw_quad_dll() to inform us that you want us to submit everything to the GPU up to that point, so that your rendering will interleave.

This has not changed going from GMS1 -> GMS2 but you may have been getting away with it before, and other drivers / gpu types (that you did not test with) may have had the same behaviour as GMS2

Russell
 
L

Lonewolff

Guest
Interesting. I'll take a look tomorrow and see if that works.

Having said that though, I do know that if you do this;

Code:
Shader_set
Draw_quad
Shader_reset
...the drawing of the quad will still be pushed outside of the shader_set / reset scope.

But again, I'll do some further testing and let you know :)
 

rwkay

GameMaker Staff
GameMaker Dev.
the draw_flush will submit everything from the GML side to the GPU before you submit anything so ordering will be preserved (it is what we do internally) - this means that any batching will be broken, but the draw order will be correct.

Russell
 
L

Lonewolff

Guest
@rwkay - Just tried out the draw flush suggestion. Still the same behaviour. The draw call from the DLL gets pushed outside of the draw event.

 

rwkay

GameMaker Staff
GameMaker Dev.
Please file a bug with a simple example (include the source to the extension) and we will take a look, I think you are doing something wrong there, but without seeing your code it will be difficult to tell.

Russell
 
L

Lonewolff

Guest
@rwkay - FWIW, this is presently the entirety of the dll call in the draw event (if this sheds any light)

Code:
fn_export double mesh_draw()
{
    struct Float2
    {
        float x, y;
    };

    unsigned int stride = sizeof(Float2);
    unsigned int offset = 0;
    d3dContext->IASetInputLayout(d3dInputLayoutXY);
    d3dContext->IASetVertexBuffers(0, 1, &bufferMesh, &stride, &offset);
    d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    d3dContext->Draw(3, 0);        // One triangle

    return 1;
}
So there is nothing really magical going on.

It draws a triangle fine, but not when it should be (as depicted in the render capture above).
 
S

Sam (Deleted User)

Guest
At the very least, we should have a way to get the function address for window_handle() - that way, we can access the window's handle on Windows, Mac, and Linux without needing to waste our function's arguments on that. Keep in mind - we only get to use up to 4 arguments when any one of them is a char * or pointer. So that is one of the biggest reasons this would be useful, other than the fact we need it to make our extensions more user-friendly. A lot of users who don't make extensions but do use them won't understand why there are functions that require an argument to be window_handle(), it just looks bad.
 

GMWolf

aka fel666
A lot of users who don't make extensions but do use them won't understand why there are functions that require an argument to be window_handle(), it just looks bad.
just hide it in your own function?
I sometimes end up making internal version and public version of scripts to call weird stuff.
Often its because I have to pass data around on a buffer.
 
S

Sam (Deleted User)

Guest
How do you make a script internal or public? I thought that was only possible in pre-studio extensions, and now they were all public?
 
S

Sam (Deleted User)

Guest
Oh ok, I gotcha. But I do remember in the GM7 extension maker you could include scripts that don't show up anywhere in the IDE, except the code editor's intellisense. Then again if it shows up anywhere it's still considered public so I see what you mean. The major thing is I just don't want certain scripts to be view-able from the resource tree, like GM 8.1 and below extensions worked.
 

GMWolf

aka fel666
Oh ok, I gotcha. But I do remember in the GM7 extension maker you could include scripts that don't show up anywhere in the IDE, except the code editor's intellisense. Then again if it shows up anywhere it's still considered public so I see what you mean. The major thing is I just don't want certain scripts to be view-able from the resource tree, like GM 8.1 and below extensions worked.
eh, thats not how GM works! Its all about making averything horible and clogging your resource tree, and your intelisense :p
 

kburkhart84

Firehammer Games
Just FYI, The issue with internal scripts I've seen it handled(and do it myself) by just making it a separate folder inside your asset's folder. If you type the underscores it will still show up in intellisense though. But I generally get around that too. My FHInput extension for example, all scripts that you should be calling start with fhinput**** and then any internal scripts start with _fhinput*** so you can easily filter the scripts in intellisense by typing fhinput, and then if other assets or the user have scripts that start with underscore, then my fhinput scripts will be filtered out of intellisense will be filtered away as soon as they start typing once a letter differs from "_fhinput." This isn't the perfect solution, as something done directly by Yoyo to hide those scripts could be better. But since it is generally a good idea for many of us to allow the internal source to be seen/edited anyway, it isn't bad.
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
They where always all public. I just add internal, or a couple underscores in front.
Not super neat but hey, GML never ends up neat...
y'all might be too busy complaining about things

How do you make a script internal or public? I thought that was only possible in pre-studio extensions, and now they were all public?
You set a script/function's help to be an empty string and that hides it from auto-completion.
In GMS2 there is currently a bug where this (and "hidden" option in JSON) is ignored and scripts/functions are still shown in auto-completion (albeit without argument info).

With window_handle in particular, you can send it to extension during initialization, and then use that handle - I don't think there's any scenario where game window handle could suddenly change.
 
S

Sam (Deleted User)

Guest
With window_handle in particular, you can send it to extension during initialization, and then use that handle - I don't think there's any scenario where game window handle could suddenly change.
Yeah, I'll do that if I ever need it. I was actually thinking this would be useful to some users who aren't in my position - for whatever reason I can't upload to the marketplace actual "extensions" and by that I mean there is a bug where if I try to upload the "Extensions" resource folder, in GMS 1.4 it acts as though it uploads OK, but when I download my extension from the MP to see if everything uploaded correctly the only thing that never actually downloads is the Extensions resource folder files, so to make it consistent between my GMS 1.4 and 2 versions of my assets, I use scripts and included files instead, which I'm cool with. Half the time I need extra GML put in with my native code so I need it as a script and not a directly called function from the extensions folder anyway. Anyway that's why I never filed a bug for it. It's not a huge deal to me.

Again, thanks for your suggestion, that is very useful info for people who didn't already know that, and I am one of those people. I'll probably do that once GMS 1.4 assets officially die off the MP, if that ever happens.
 

kburkhart84

Firehammer Games
Way back when I had made an extension for GM8 that would do bit by bit loading of external sprites, sounds, etc.. from zip files, and then automatically unloading those resources later(similar to what you do with texture pages now if you so desire). It was using a DLL. I only had scripts actually call the DLL functions, wrapping all of that in GML instead of asking the user to use the "external_call" functions. This made it much easier to add stuff to the GML as needed. I wouldn't ever have the user calling DLL functions directly, though I haven't done anything with a DLL recently.
 
Top