GameMonkey Script

Calling a gmFunction pointer from C++ with parameters
Page 1 of 1

Author:  mrbarrysoftware [ Sat Sep 22, 2012 6:36 pm ]
Post subject:  Calling a gmFunction pointer from C++ with parameters

Hello ladies and gents,

I noticed in the reference pdf, there is code to call a gmFunction with parameters like this:

#include "gmCall.h"                      // This header contains the helper class
gmMachine machine;                       // Instance of machine exists somewhere.
// Calls a script function: " global Add = function(a, b) {return a + b;} "
gmCall call;                             // Create instance of call helper
int resultInt = 0;                       // The variable to store our future return value.
if(call.BeginGlobalFunction(&machine, "Add"))     // A global function called 'Add'. 
                                            False is returned here if function was not found.
  call.AddParamInt(3);                   // Parameter 1 is an int of this value
  call.AddParamInt(5);                   // Parameter 2 is an int of this value
  call.End();                            // Finish the call and set the return value
  call.GetReturnedInt(resultInt);        // We want to know about the return value which is an int
// resultInt now contains 8

Unfortunately, at one point or another, gmCall.h has been removed, and I don't know if that means that the gmCall class has also been removed (not sure which file to check).

I've done a work-around by doing:

gmMachine *vm = getVirtualMachine(); // Gets the current valid gmMachine

gmuint32 now = vm->GetTime();
gmuint32 delta = now - callback.last_executed_at;
gmTableObject *fthis = vm->AllocTableObject();
fthis->Set( vm, "delta", gmVariable( (int)delta ) );
fthis->Set( vm, "some_String", gmVariable( "test" ) );

vm->ExecuteFunction( callback.func, NULL, true, new gmVariable(fthis) );

callback.last_executed_at = now;

This is fine, as I can just use this.variable, but I think it's more appropriate to have the information I'm passing as variables.

Any help would be super!


Author:  Greg [ Sun Sep 23, 2012 1:12 am ]
Post subject:  Re: Calling a gmFunction pointer from C++ with parameters

The gmCall class is an optional helper class. It's found in the \binds folder along with other helpers like gmGCRoot (think .Net gcroot<>) for C++ owned script objects.

The helpers are there to use 'asis' or use as examples to write your own specialized helpers.

Author:  mrbarrysoftware [ Sun Sep 23, 2012 1:26 am ]
Post subject:  Re: Calling a gmFunction pointer from C++ with parameters

Is it possible to push the parameters without using gmCall?


Edit: Nevermind, checked out the gmCall class, and it looks pretty straight forward - it may be good to document this raw process more than documenting a wrapper/helper class, but that's sort of neat.

Author:  Greg [ Sun Sep 23, 2012 4:13 am ]
Post subject:  Re: Calling a gmFunction pointer from C++ with parameters

You're just encountering the lack of documentation :|

Even thought he FAQ does say something like 'Add some ready made bindings and helpers from src\binds as you desire' The fact is not all the source files are platform independent (eg. gmSystemLib), so simply dumping them all into your project doesn't always work.

I've just made the link to the Oli's GameDev articles a sticky since this is the most valuable documentation resource new users should read.

Author:  mrbarrysoftware [ Thu Sep 27, 2012 3:16 pm ]
Post subject:  Re: Calling a gmFunction pointer from C++ with parameters

For anyone looking for a direct answers, this is what I ended up doing:

// Note: this->m_gmcallbacks is a std::vector< std::pair< gmFunctionObject *, gmint > >
// the gmint is the amount of time (delta) since the last execution of this callback.
// If I had any more information, I'd create a struct instead like this:
// typedef struct {
//  gmFunctionObject *func;
//  gmint delta;
//  // more stuff here....
// } OverlayGMCallback;

gmuint32 now = vm->GetTime();
gmuint32 delta = now - this->m_gmcallbacks[i].second;

// The thread is necessary to push a lot of information.
gmThread *thread = vm->CreateThread();
gmTableObject *ooverlay = vm->AllocTableObject();

gmVariable returnVal;

// Prep the function
thread->PushNewUser( (void *)this, vm->GetTypeId("Overlay") ); // 'this' (called from inside my Overlay class, fyi, which is why I'm passing (void *)this)
thread->PushFunction( this->m_gmcallbacks[i].first ); // the called function

// Add parameters:
thread->Push( gmVariable( (int)delta ) );
// Push as many things as necessary, however, it must match the number in the thread->PushStackFrame() parameter!

// Execute
int state = thread->PushStackFrame( 1 ); // Number of parameters, must match number of calls above!

if (state != gmThread::KILLED) {
   state = thread->Sys_Execute(&returnVal);
} else {
   returnVal = *(thread->GetTop() - 1);
   vm->Sys_SwitchState(thread, gmThread::KILLED);
// Anything you want to do with the returnVal should be done here!

this->m_gmcallbacks[i].second = now;

Page 1 of 1 All times are UTC
Powered by phpBB® Forum Software © phpBB Group