engineAPI.h
Engine/source/console/engineAPI.h
Definitions for exposing engine functionality to the control layer.
Classes:
Unmarshal data from client form to engine form.
Namespaces:
API Definition Macros
The macros in this group allow to create engine API functions that work both with the legacy console system as well as with the new engine export system.
As such, they only support those function features that are available in both systems. This means that for console-style variadic functions, the ConsoleXXX must be used and that for overloaded and/or C-style variadic functions as well as for placing functions in export scopes, DEFINE_CALLIN must be used directly.
When the console system is removed, the console thunking functionality will be removed from these macros but otherwise they will remain unchanged and in place.
_CHECK_ENGINE_INITIALIZED(fnName, returnType) ( fnName, returnType )
_CHECK_ENGINE_INITIALIZED_IMPL(fnName, returnType) ( ! ) \ { \ ( "EngineAPI: Engine not initialized when calling " #fnName ); \ return < returnType >::ReturnValue( < returnType >::ReturnValueType() ); \ }
_DefineMethodTrampoline(className, name, returnType, args) TORQUE_API < returnType >::ReturnValueType \ fn ## className ## _ ## name ( className* object, < _ ## className ## name ## frame, returnType args >::Args )\ { \ ( className::name, returnType ); \ return < returnType >::ReturnValue( \ < _ ## className ## name ## frame, returnType args >::jmp( object, ) \ ); \ }
DefineEngineFunction(name, returnType, args, defaultArgs, usage)
Define a call-in point for calling into the engine.
DefineEngineMethod(className, name, returnType, args, defaultArgs, usage)
Define a call-in point for calling a method on an engine object.
DefineEngineStaticMethod(className, name, returnType, args, defaultArgs, usage)
Define a call-in point for calling into the engine.
DefineEngineStringlyVariadicFunction(name, returnType, minArgs, maxArgs, usage) static inline returnType _fn ## name ## impl ( *, argc, *argv); \ TORQUE_API < returnType >::ReturnValueType fn ## name \ (< char*>* vec) \ { \ ( name, returnType ); \ args(vec->(), vec->address()); \ return < returnType >::ReturnValue( \ _fn ## name ## impl(, (), args) \ ); \ } \ static < (< char*>* vec) > _fn ## name ## DefaultArgs; \ static _fn ## name ## FunctionInfo( \ #name, \ &<>()(), \ usage, \ #returnType " " #name "(Vector<> args)", \ "fn" #name, \ < returnType (< char*>* vec) >(), \ &_fn ## name ## DefaultArgs, \ ( * ) &fn ## name, \ 0 \ ); \ cc_##name##_obj(,#name,_fn ## name ## impl,usage,minArgs,maxArgs); \ returnType _fn ## name ## impl( *, argc, *argv)
DefineEngineStringlyVariadicMethod(className, name, returnType, minArgs, maxArgs, usage)
DefineNewEngineFunction(name, returnType, args, defaultArgs, usage) static inline returnType _fn ## name ## impl args; \ TORQUE_API < returnType >::ReturnValueType fn ## name \ ( < returnType args >::Args ) \ { \ ( name, returnType ); \ return < returnType >::ReturnValue( \ < returnType args >::jmp( _fn ## name ## impl, ) \ ); \ } \ static < args > _fn ## name ## DefaultArgs defaultArgs; \ static _fn ## name ## FunctionInfo( \ #name, \ &<>()(), \ usage, \ #returnType " " #name #args, \ "fn" #name, \ < returnType args >(), \ &_fn ## name ## DefaultArgs, \ ( * ) &fn ## name, \ 0 \ ); \ static inline returnType _fn ## name ## impl args
DefineNewEngineMethod(className, name, returnType, args, defaultArgs, usage) struct _ ## className ## name ## frame \ { \ typedef className ObjectType; \ className* object; \ inline returnType _exec args ; \ }; \ ( className, name, returnType, args ); \ static < < _ ## className ## name ## frame, args >::FunctionType > \ _fn ## className ## name ## DefaultArgs defaultArgs; \ static _fn ## className ## name ## FunctionInfo( \ #name, \ &< className >()(), \ usage, \ "virtual " #returnType " " #name #args, \ "fn" #className "_" #name, \ < < _ ## className ## name ## frame, returnType args >::FunctionType >(), \ &_fn ## className ## name ## DefaultArgs, \ ( * ) &fn ## className ## _ ## name, \ 0 \ ); \ returnType _ ## className ## name ## frame::_exec args
DefineNewEngineStaticMethod(className, name, returnType, args, defaultArgs, usage) static inline returnType _fn ## className ## name ## impl args; \ TORQUE_API < returnType >::ReturnValueType fn ## className ## _ ## name \ ( < returnType args >::Args ) \ { \ ( className::name, returnType ); \ return < returnType >::ReturnValue( \ < returnType args >::jmp( _fn ## className ## name ## impl, ) \ ); \ } \ static < args > _fn ## className ## name ## DefaultArgs defaultArgs; \ static _fn ## name ## FunctionInfo( \ #name, \ &< className >()(), \ usage, \ #returnType " " #name #args, \ "fn" #className "_" #name, \ < returnType args >(), \ &_fn ## className ## name ## DefaultArgs, \ ( * ) &fn ## className ## _ ## name, \ 0 \ ); \ static inline returnType _fn ## className ## name ## impl args
Marshalling
Functions for converting to/from string-based data representations.
note:This functionality is specific to the console interop.
EngineMarshallData(bool arg, S32 & argc, ConsoleValueRef * argv)
const char *
EngineMarshallData(bool value)
EngineMarshallData(char * arg, S32 & argc, ConsoleValueRef * argv)
EngineMarshallData(const char * arg, S32 & argc, ConsoleValueRef * argv)
const char *
EngineMarshallData(const char * str)
EngineMarshallData(const T & arg, S32 & argc, ConsoleValueRef * argv)
Marshal data from native into client form stored directly in client function invocation vector.
const char *
EngineMarshallData(const T & value)
Marshal a single piece of data from native into client form.
const char *
EngineMarshallData(const T * object)
EngineMarshallData(const T * object, S32 & argc, ConsoleValueRef * argv)
EngineMarshallData(F32 arg, S32 & argc, ConsoleValueRef * argv)
EngineMarshallData(S32 arg, S32 & argc, ConsoleValueRef * argv)
const char *
EngineMarshallData(T * object)
EngineMarshallData(T * object, S32 & argc, ConsoleValueRef * argv)
EngineMarshallData(U32 arg, S32 & argc, ConsoleValueRef * argv)
const char *
EngineMarshallData(U32 value)
Thunking
Internal functionality for thunks placed between TorqueScript calls of engine functions and their native implementations.
note:The functionality in this group is specific to the console interop system.
bool
_EngineConsoleThunkReturnValue(bool value)
const char *
_EngineConsoleThunkReturnValue(const char * value)
const char *
const char *
_EngineConsoleThunkReturnValue(const T & value)
const char *
_EngineConsoleThunkReturnValue(const T * value)
const char *
_EngineConsoleThunkReturnValue(T * value)
Public Defines
IMPLEMENT_CALLBACK(class, name, returnType, args, argNames, usageString)
Matching implement for DECLARE_CALLBACK.
IMPLEMENT_CONSOLE_CALLBACK(class, name, returnType, args, argNames, usageString) returnType class::name ## _callback args \ { \ ( ) \ { \ static sName = ->insert( #name ); \ cbh( sName, this ); \ return returnType( cbh.call< returnType > argNames ); \ } \ return returnType(); \ } \ namespace { \ _ ## class ## name ## header( \ #returnType, #args, "" ); \ _ ## class ## name ## obj( #class, #name, usageString, &_ ## class ## name ## header ); \ }
IMPLEMENT_GLOBAL_CALLBACK(name, returnType, args, argNames, usageString) ( cb ## name, name,, returnType, args, 0, usageString ); \ returnType name ## _callback args \ { \ ( cb ## name ) \ return returnType( cb ## name argNames ); \ ( ) \ { \ static sName = ->insert( #name ); \ cbh( sName, ); \ return returnType( cbh.call< returnType > argNames ); \ } \ return returnType(); \ } \ namespace { \ _ ## name ## header( \ #returnType, #args, "" ); \ _ ## name ## obj( , #name, usageString, &_ ## name ## header ); \ }
Used to define global callbacks not associated with any particular class or namespace.
IMPLEMENT_NEW_CALLBACK(class, name, returnType, args, argNames, usageString) struct _ ## class ## name ## frame { typedef class ObjectType; }; \ TORQUE_API < _ ## class ## name ## frame, returnType args >::FunctionType* cb ## class ## _ ## name; \ TORQUE_API set_cb ## class ## _ ## name( \ < _ ## class ## name ## frame, returnType args >::FunctionType fn ) \ { cb ## class ## _ ## name = fn; } \ < _ ## class ## name ## frame, returnType args >::FunctionType* cb ## class ## _ ## name; \ namespace { \ :: _cb ## class ## name( \ #name, \ &::< class >()(), \ usageString, \ "virtual " #returnType " " #name #args, \ "cb" #class "_" #name, \ ::< < _ ## class ## name ## frame, returnType args >::FunctionType >(), \ , \ &cb ## class ## _ ## name, \ \ ); \ } \ returnType class::name ## _callback args \ { \ ( cb ## class ## _ ## name ) { \ cbh( this, reinterpret_cast< * >( cb ## class ## _ ## name ) ); \ return returnType( cbh.call< returnType > argNames ); \ } \ return returnType(); \ }
Detailed Description
Definitions for exposing engine functionality to the control layer.
This file provides a convenience layer around the underlying engine interop system (which at the moment still includes the legacy TorqueScript interop a.k.a. "console system"). The macros exposed here will automatically take care of all marshalling, value type constraints, reflection info instancing, etc. involved in defining engine API call-ins and call-outs.
note:At the moment, this file supplies both the legacy TorqueScript console system as well as the new engine export system with the structures and information they need. In the near future, the console-based parts will get purged. This will not result in visible changes to users of the functionality here except for the string-based marshalling functions currently exposed (which will also disappear).
API Definition Macros
The macros in this group allow to create engine API functions that work both with the legacy console system as well as with the new engine export system.
As such, they only support those function features that are available in both systems. This means that for console-style variadic functions, the ConsoleXXX must be used and that for overloaded and/or C-style variadic functions as well as for placing functions in export scopes, DEFINE_CALLIN must be used directly.
When the console system is removed, the console thunking functionality will be removed from these macros but otherwise they will remain unchanged and in place.
_CHECK_ENGINE_INITIALIZED(fnName, returnType) ( fnName, returnType )
_CHECK_ENGINE_INITIALIZED_IMPL(fnName, returnType) ( ! ) \ { \ ( "EngineAPI: Engine not initialized when calling " #fnName ); \ return < returnType >::ReturnValue( < returnType >::ReturnValueType() ); \ }
_DefineMethodTrampoline(className, name, returnType, args) TORQUE_API < returnType >::ReturnValueType \ fn ## className ## _ ## name ( className* object, < _ ## className ## name ## frame, returnType args >::Args )\ { \ ( className::name, returnType ); \ return < returnType >::ReturnValue( \ < _ ## className ## name ## frame, returnType args >::jmp( object, ) \ ); \ }
DefineEngineFunction(name, returnType, args, defaultArgs, usage)
Define a call-in point for calling into the engine.
Parameters:
name | The name of the function as it should be seen by the control layer. |
returnType | The value type returned to the control layer. |
args | The argument list as it would appear on the function definition |
defaultArgs | The list of default argument values. |
usage | The usage doc string for the engine API reference. |
DefineEngineFunction( myFunction, int, ( float f, const String& s ), ( "value for s" ), "This is my function." ) { return int( f ) + dAtoi( s ); }
DefineEngineMethod(className, name, returnType, args, defaultArgs, usage)
Define a call-in point for calling a method on an engine object.
Parameters:
name | The name of the C++ class. |
name | The name of the method as it should be seen by the control layer. |
returnType | The value type returned to the control layer. |
args | The argument list as it would appear on the function definition |
defaultArgs | The list of default argument values. |
usage | The usage doc string for the engine API reference. |
DefineEngineMethod( MyClass, myMethod, int, ( float f, const String& s ), ( "value for s" ), "This is my method." ) { return object->someMethod( f, s ); }
DefineEngineStaticMethod(className, name, returnType, args, defaultArgs, usage)
Define a call-in point for calling into the engine.
Unlike with DefineEngineFunction, the statically callable function will be confined to the namespace of the given class.
Parameters:
classname | The name of the C++ class (or a registered export scope). |
name | The name of the method as it should be seen by the control layer. |
returnType | The value type returned to the control layer. |
args | The argument list as it would appear on the function definition |
defaultArgs | The list of default argument values. |
usage | The usage doc string for the engine API reference. |
DefineEngineStaticMethod( MyClass, myMethod, int, ( float f, string s ), ( "value for s" ), "This is my method." ) { }
DefineEngineStringlyVariadicFunction(name, returnType, minArgs, maxArgs, usage) static inline returnType _fn ## name ## impl ( *, argc, *argv); \ TORQUE_API < returnType >::ReturnValueType fn ## name \ (< char*>* vec) \ { \ ( name, returnType ); \ args(vec->(), vec->address()); \ return < returnType >::ReturnValue( \ _fn ## name ## impl(, (), args) \ ); \ } \ static < (< char*>* vec) > _fn ## name ## DefaultArgs; \ static _fn ## name ## FunctionInfo( \ #name, \ &<>()(), \ usage, \ #returnType " " #name "(Vector<> args)", \ "fn" #name, \ < returnType (< char*>* vec) >(), \ &_fn ## name ## DefaultArgs, \ ( * ) &fn ## name, \ 0 \ ); \ cc_##name##_obj(,#name,_fn ## name ## impl,usage,minArgs,maxArgs); \ returnType _fn ## name ## impl( *, argc, *argv)
DefineEngineStringlyVariadicMethod(className, name, returnType, minArgs, maxArgs, usage)
DefineNewEngineFunction(name, returnType, args, defaultArgs, usage) static inline returnType _fn ## name ## impl args; \ TORQUE_API < returnType >::ReturnValueType fn ## name \ ( < returnType args >::Args ) \ { \ ( name, returnType ); \ return < returnType >::ReturnValue( \ < returnType args >::jmp( _fn ## name ## impl, ) \ ); \ } \ static < args > _fn ## name ## DefaultArgs defaultArgs; \ static _fn ## name ## FunctionInfo( \ #name, \ &<>()(), \ usage, \ #returnType " " #name #args, \ "fn" #name, \ < returnType args >(), \ &_fn ## name ## DefaultArgs, \ ( * ) &fn ## name, \ 0 \ ); \ static inline returnType _fn ## name ## impl args
DefineNewEngineMethod(className, name, returnType, args, defaultArgs, usage) struct _ ## className ## name ## frame \ { \ typedef className ObjectType; \ className* object; \ inline returnType _exec args ; \ }; \ ( className, name, returnType, args ); \ static < < _ ## className ## name ## frame, args >::FunctionType > \ _fn ## className ## name ## DefaultArgs defaultArgs; \ static _fn ## className ## name ## FunctionInfo( \ #name, \ &< className >()(), \ usage, \ "virtual " #returnType " " #name #args, \ "fn" #className "_" #name, \ < < _ ## className ## name ## frame, returnType args >::FunctionType >(), \ &_fn ## className ## name ## DefaultArgs, \ ( * ) &fn ## className ## _ ## name, \ 0 \ ); \ returnType _ ## className ## name ## frame::_exec args
DefineNewEngineStaticMethod(className, name, returnType, args, defaultArgs, usage) static inline returnType _fn ## className ## name ## impl args; \ TORQUE_API < returnType >::ReturnValueType fn ## className ## _ ## name \ ( < returnType args >::Args ) \ { \ ( className::name, returnType ); \ return < returnType >::ReturnValue( \ < returnType args >::jmp( _fn ## className ## name ## impl, ) \ ); \ } \ static < args > _fn ## className ## name ## DefaultArgs defaultArgs; \ static _fn ## name ## FunctionInfo( \ #name, \ &< className >()(), \ usage, \ #returnType " " #name #args, \ "fn" #className "_" #name, \ < returnType args >(), \ &_fn ## className ## name ## DefaultArgs, \ ( * ) &fn ## className ## _ ## name, \ 0 \ ); \ static inline returnType _fn ## className ## name ## impl args
Marshalling
Functions for converting to/from string-based data representations.
note:This functionality is specific to the console interop.
EngineMarshallData(bool arg, S32 & argc, ConsoleValueRef * argv)
EngineMarshallData(bool value)
EngineMarshallData(char * arg, S32 & argc, ConsoleValueRef * argv)
EngineMarshallData(const char * arg, S32 & argc, ConsoleValueRef * argv)
EngineMarshallData(const char * str)
EngineMarshallData(const T & arg, S32 & argc, ConsoleValueRef * argv)
Marshal data from native into client form stored directly in client function invocation vector.
EngineMarshallData(const T & value)
Marshal a single piece of data from native into client form.
EngineMarshallData(const T * object)
EngineMarshallData(const T * object, S32 & argc, ConsoleValueRef * argv)
EngineMarshallData(F32 arg, S32 & argc, ConsoleValueRef * argv)
EngineMarshallData(S32 arg, S32 & argc, ConsoleValueRef * argv)
EngineMarshallData(T * object)
EngineMarshallData(T * object, S32 & argc, ConsoleValueRef * argv)
EngineMarshallData(U32 arg, S32 & argc, ConsoleValueRef * argv)
EngineMarshallData(U32 value)
Thunking
Internal functionality for thunks placed between TorqueScript calls of engine functions and their native implementations.
note:The functionality in this group is specific to the console interop system.
_EngineConsoleThunkReturnValue(bool value)
_EngineConsoleThunkReturnValue(const char * value)
_EngineConsoleThunkReturnValue(const String & str)
_EngineConsoleThunkReturnValue(const T & value)
_EngineConsoleThunkReturnValue(const T * value)
_EngineConsoleThunkReturnValue(F32 value)
_EngineConsoleThunkReturnValue(S32 value)
_EngineConsoleThunkReturnValue(T * value)
Public Defines
IMPLEMENT_CALLBACK(class, name, returnType, args, argNames, usageString)
Matching implement for DECLARE_CALLBACK.
@warn With the new interop system, method-style callbacks must not be triggered on object that are being created! This is because the control layer will likely not yet have a fully valid wrapper object in place for the EngineObject under construction.
IMPLEMENT_CONSOLE_CALLBACK(class, name, returnType, args, argNames, usageString) returnType class::name ## _callback args \ { \ ( ) \ { \ static sName = ->insert( #name ); \ cbh( sName, this ); \ return returnType( cbh.call< returnType > argNames ); \ } \ return returnType(); \ } \ namespace { \ _ ## class ## name ## header( \ #returnType, #args, "" ); \ _ ## class ## name ## obj( #class, #name, usageString, &_ ## class ## name ## header ); \ }
IMPLEMENT_GLOBAL_CALLBACK(name, returnType, args, argNames, usageString) ( cb ## name, name,, returnType, args, 0, usageString ); \ returnType name ## _callback args \ { \ ( cb ## name ) \ return returnType( cb ## name argNames ); \ ( ) \ { \ static sName = ->insert( #name ); \ cbh( sName, ); \ return returnType( cbh.call< returnType > argNames ); \ } \ return returnType(); \ } \ namespace { \ _ ## name ## header( \ #returnType, #args, "" ); \ _ ## name ## obj( , #name, usageString, &_ ## name ## header ); \ }
Used to define global callbacks not associated with any particular class or namespace.
IMPLEMENT_NEW_CALLBACK(class, name, returnType, args, argNames, usageString) struct _ ## class ## name ## frame { typedef class ObjectType; }; \ TORQUE_API < _ ## class ## name ## frame, returnType args >::FunctionType* cb ## class ## _ ## name; \ TORQUE_API set_cb ## class ## _ ## name( \ < _ ## class ## name ## frame, returnType args >::FunctionType fn ) \ { cb ## class ## _ ## name = fn; } \ < _ ## class ## name ## frame, returnType args >::FunctionType* cb ## class ## _ ## name; \ namespace { \ :: _cb ## class ## name( \ #name, \ &::< class >()(), \ usageString, \ "virtual " #returnType " " #name #args, \ "cb" #class "_" #name, \ ::< < _ ## class ## name ## frame, returnType args >::FunctionType >(), \ , \ &cb ## class ## _ ## name, \ \ ); \ } \ returnType class::name ## _callback args \ { \ ( cb ## class ## _ ## name ) { \ cbh( this, reinterpret_cast< * >( cb ## class ## _ ## name ) ); \ return returnType( cbh.call< returnType > argNames ); \ } \ return returnType(); \ }
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#ifndef _ENGINEAPI_H_ 25#define _ENGINEAPI_H_ 26 27#include <tuple> 28#include <utility> 29 30#ifndef _FIXEDTUPLE_H_ 31#include "fixedTuple.h" 32#endif 33 34#ifndef _CONSOLETYPES_H_ 35#include "console/consoleTypes.h" 36#endif 37 38#ifndef _CONSOLE_H_ 39#include "console/console.h" 40#endif 41 42#ifndef _STRINGFUNCTIONS_H_ 43#include "core/strings/stringFunctions.h" 44#endif 45 46#ifndef _SIMOBJECT_H_ 47#include "console/simObject.h" 48#endif 49 50#ifndef _ENGINEFUNCTIONS_H_ 51#include "console/engineFunctions.h" 52#endif 53 54// Whatever types are used in API definitions, their DECLAREs must be visible to the 55// macros. We include the basic primitive and struct types here. 56 57#ifndef _ENGINEPRIMITIVES_H_ 58 #include "console/enginePrimitives.h" 59#endif 60#ifndef _ENGINESTRUCTS_H_ 61 #include "console/engineStructs.h" 62#endif 63 64// Needed for the executef macros. Blame GCC. 65#ifndef _SIMEVENTS_H_ 66#include "console/simEvents.h" 67#endif 68 69 70/// @file 71/// Definitions for exposing engine functionality to the control layer. 72/// 73/// This file provides a convenience layer around the underlying engine interop system (which at 74/// the moment still includes the legacy TorqueScript interop a.k.a. "console system"). The 75/// macros exposed here will automatically take care of all marshalling, value type constraints, 76/// reflection info instancing, etc. involved in defining engine API call-ins and call-outs. 77/// 78/// @note At the moment, this file supplies both the legacy TorqueScript console system as well 79/// as the new engine export system with the structures and information they need. In the 80/// near future, the console-based parts will get purged. This will not result in visible 81/// changes to users of the functionality here except for the string-based marshalling 82/// functions currently exposed (which will also disappear). 83 84 85 86//TODO: Disable warning for extern "C" functions returning UDTs for now; need to take a closer look at this 87#pragma warning( disable : 4190 ) 88 89 90 91// Disable some VC warnings that are irrelevant to us. 92#pragma warning( push ) 93#pragma warning( disable : 4510 ) // default constructor could not be generated; all the Args structures are never constructed by us 94#pragma warning( disable : 4610 ) // can never be instantiated; again Args is never constructed by us 95 96 97namespace engineAPI { 98 99 /// Flag for enabling legacy console behavior in the interop system while 100 /// we still have it around. Will disappear along with console. 101 extern bool gUseConsoleInterop; 102 103 /// Flag to allow engine functions to detect whether the engine had been 104 /// initialized or shut down. 105 extern bool gIsInitialized; 106} 107 108/// @name Marshalling 109/// 110/// Functions for converting to/from string-based data representations. 111/// 112/// @note This functionality is specific to the console interop. 113/// @{ 114 115/// Marshal a single piece of data from native into client form. 116template< typename T > 117inline const char* EngineMarshallData( const T& value ) 118{ 119 return castConsoleTypeToString( value ); 120} 121inline const char* EngineMarshallData( bool value ) 122{ 123 if( value ) 124 return "1"; 125 else 126 return "0"; 127} 128inline const char* EngineMarshallData( const char* str ) 129{ 130 // The API assumes that if you pass a plain "const char*" through it, then you are referring 131 // to string storage with non-local lifetime that can be safely passed to the control layer. 132 return str; 133} 134template< typename T > 135inline const char* EngineMarshallData( T* object ) 136{ 137 return ( object ? object->getIdString() : "0" ); 138} 139template< typename T > 140inline const char* EngineMarshallData( const T* object ) 141{ 142 return ( object ? object->getIdString() : "0" ); 143} 144inline const char* EngineMarshallData( U32 value ) 145{ 146 return EngineMarshallData( S32( value ) ); 147} 148 149/// Marshal data from native into client form stored directly in 150/// client function invocation vector. 151template< typename T > 152inline void EngineMarshallData( const T& arg, S32& argc, ConsoleValueRef *argv ) 153{ 154 argv[ argc ] = castConsoleTypeToString( arg ); 155 argc ++; 156} 157inline void EngineMarshallData( bool arg, S32& argc, ConsoleValueRef *argv ) 158{ 159 if( arg ) 160 argv[ argc ] = 1; 161 else 162 argv[ argc ] = 0; 163 argc ++; 164} 165inline void EngineMarshallData( S32 arg, S32& argc, ConsoleValueRef *argv ) 166{ 167 argv[ argc ] = arg; 168 argc ++; 169} 170inline void EngineMarshallData( U32 arg, S32& argc, ConsoleValueRef *argv ) 171{ 172 EngineMarshallData( S32( arg ), argc, argv ); 173} 174inline void EngineMarshallData( F32 arg, S32& argc, ConsoleValueRef *argv ) 175{ 176 argv[ argc ] = arg; 177 argc ++; 178} 179inline void EngineMarshallData( const char* arg, S32& argc, ConsoleValueRef *argv ) 180{ 181 argv[ argc ] = arg; 182 argc ++; 183} 184inline void EngineMarshallData( char* arg, S32& argc, ConsoleValueRef *argv ) 185{ 186 argv[ argc ] = arg; 187 argc ++; 188} 189 190template< typename T > 191inline void EngineMarshallData( T* object, S32& argc, ConsoleValueRef *argv ) 192{ 193 argv[ argc ] = object ? object->getId() : 0; 194 argc ++; 195} 196template< typename T > 197inline void EngineMarshallData( const T* object, S32& argc, ConsoleValueRef *argv ) 198{ 199 argv[ argc ] = object ? object->getId() : 0; 200 argc ++; 201} 202 203/// Unmarshal data from client form to engine form. 204/// 205/// This is wrapped in an a struct as partial specializations on function 206/// templates are not allowed in C++. 207template< typename T > 208struct EngineUnmarshallData 209{ 210 T operator()( const char* str ) const 211 { 212 T value; 213 castConsoleTypeFromString( value, str ); 214 return value; 215 } 216}; 217template<> 218struct EngineUnmarshallData< S32 > 219{ 220 S32 operator()( ConsoleValueRef &ref ) const 221 { 222 return (S32)ref; 223 } 224 225 S32 operator()( const char* str ) const 226 { 227 return dAtoi( str ); 228 } 229}; 230template<> 231struct EngineUnmarshallData< U32 > 232{ 233 U32 operator()( ConsoleValueRef &ref ) const 234 { 235 return (U32)((S32)ref); 236 } 237 238 U32 operator()( const char* str ) const 239 { 240 return dAtoui( str ); 241 } 242}; 243template<> 244struct EngineUnmarshallData< F32 > 245{ 246 F32 operator()( ConsoleValueRef &ref ) const 247 { 248 return (F32)ref; 249 } 250 251 F32 operator()( const char* str ) const 252 { 253 return dAtof( str ); 254 } 255}; 256template<> 257struct EngineUnmarshallData< U8 > 258{ 259 U8 operator()( ConsoleValueRef &ref ) const 260 { 261 return (U8)((S32)ref); 262 } 263 264 U8 operator()( const char* str ) const 265 { 266 return dAtoui( str ); 267 } 268}; 269template<> 270struct EngineUnmarshallData< const char* > 271{ 272 const char* operator()( ConsoleValueRef &ref ) const 273 { 274 return ref.getStringValue(); 275 } 276 277 const char* operator()( const char* str ) const 278 { 279 return str; 280 } 281}; 282template< typename T > 283struct EngineUnmarshallData< T* > 284{ 285 T* operator()( ConsoleValueRef &ref ) const 286 { 287 return dynamic_cast< T* >( Sim::findObject( ref.getStringValue() ) ); 288 } 289 290 T* operator()( const char* str ) const 291 { 292 return dynamic_cast< T* >( Sim::findObject( str ) ); 293 } 294}; 295template<> 296struct EngineUnmarshallData< void > 297{ 298 void operator()( ConsoleValueRef& ) const {} 299 void operator()( const char* ) const {} 300}; 301 302 303template<> 304struct EngineUnmarshallData< ConsoleValueRef > 305{ 306 ConsoleValueRef operator()( ConsoleValueRef ref ) const 307 { 308 return ref; 309 } 310}; 311 312/// @} 313 314 315/// @name C to C++ Trampolines 316/// 317/// The trampolines serve two purposes: 318/// 319/// For one, they ensure that no matter what argument types are specified by users of the engine API macros, the correct 320/// argument value types are enforced on the functions exported by the engine. Let's say, for example, the user writes 321/// a function that takes a "Point3F direction" argument, then the template machinery here will automatically expose an 322/// API function that takes a "Point3F& direction" argument. 323/// 324/// Secondly, the templates jump the incoming calls from extern "C" space into C++ space. This is mostly relevant for 325/// methods only as they will need an implicit object type argument. 326/// 327/// @{ 328 329// Helper type to factor out commonalities between function and method trampolines. 330 331 332template<typename T> struct _EngineTrampoline { 333 struct Args {}; 334}; 335 336template< typename R, typename ...ArgTs > 337struct _EngineTrampoline< R( ArgTs ... ) > 338{ 339 template<typename T> using AVT = typename EngineTypeTraits<T>::ArgumentValueType; 340 typedef fixed_tuple<AVT<ArgTs> ...> Args; 341 Args argT; 342}; 343 344template< typename T > 345struct _EngineFunctionTrampolineBase : public _EngineTrampoline< T > 346{ 347 typedef T FunctionType; 348}; 349 350// Trampolines for any call-ins that aren't methods. 351template< typename T > 352struct _EngineFunctionTrampoline {}; 353 354template< typename R, typename ...ArgTs > 355struct _EngineFunctionTrampoline< R(ArgTs...) > : public _EngineFunctionTrampolineBase< R(ArgTs...) > 356{ 357private: 358 using Super = _EngineFunctionTrampolineBase< R(ArgTs...) >; 359 using SelfType = _EngineFunctionTrampoline< R(ArgTs...) >; 360 using ArgsType = typename _EngineFunctionTrampolineBase< R(ArgTs ...) >::Args; 361 362 template<size_t ...> struct Seq {}; 363 template<size_t N, size_t ...S> struct Gens : Gens<N-1, N-1, S...> {}; 364 template<size_t ...I> struct Gens<0, I...>{ typedef Seq<I...> type; }; 365 366 template<size_t I> 367 static typename fixed_tuple_element<I, fixed_tuple<ArgTs...>>::type getAndToType(const ArgsType& args) { 368 return EngineTypeTraits<typename fixed_tuple_element<I, fixed_tuple<ArgTs...>>::type>::ArgumentToValue(fixed_tuple_accessor<I>::get(args)); 369 } 370 371 template<size_t ...I> 372 static R dispatchHelper(typename Super::FunctionType fn, const ArgsType& args, Seq<I...>) { 373 return R( fn(SelfType::template getAndToType<I>(args) ...) ); 374 } 375 376 using SeqType = typename Gens<sizeof...(ArgTs)>::type; 377public: 378 static R jmp(typename Super::FunctionType fn, const ArgsType& args ) 379 { 380 return dispatchHelper(fn, args, SeqType()); 381 } 382}; 383 384// Trampolines for engine methods 385 386template< typename T > 387struct _EngineMethodTrampolineBase : public _EngineTrampoline< T > {}; 388 389template< typename Frame, typename T > 390struct _EngineMethodTrampoline {}; 391 392template< typename Frame, typename R, typename ...ArgTs > 393struct _EngineMethodTrampoline< Frame, R(ArgTs ...) > : public _EngineMethodTrampolineBase< R(ArgTs ...) > 394{ 395 using FunctionType = R( typename Frame::ObjectType*, ArgTs ...); 396private: 397 using Super = _EngineMethodTrampolineBase< R(ArgTs ...) >; 398 using SelfType = _EngineMethodTrampoline< Frame, R(ArgTs ...) >; 399 using ArgsType = typename _EngineMethodTrampolineBase< R(ArgTs ...) >::Args; 400 401 template<size_t ...> struct Seq {}; 402 template<size_t N, size_t ...S> struct Gens : Gens<N-1, N-1, S...> {}; 403 template<size_t ...I> struct Gens<0, I...>{ typedef Seq<I...> type; }; 404 405 template<size_t I> 406 static typename fixed_tuple_element<I, fixed_tuple<ArgTs...>>::type getAndToType(const ArgsType& args) { 407 return EngineTypeTraits<typename fixed_tuple_element<I, fixed_tuple<ArgTs...>>::type>::ArgumentToValue(fixed_tuple_accessor<I>::get(args)); 408 } 409 410 template<size_t ...I> 411 static R dispatchHelper(Frame f, const ArgsType& args, Seq<I...>) { 412 return R(f._exec(SelfType::template getAndToType<I>(args) ...)); 413 } 414 415 using SeqType = typename Gens<sizeof...(ArgTs)>::type; 416public: 417 static R jmp( typename Frame::ObjectType* object, const ArgsType& args ) 418 { 419 420 Frame f; 421 f.object = object; 422 return dispatchHelper(f, args, SeqType()); 423 } 424}; 425 426/// @} 427 428 429/// @name Thunking 430/// 431/// Internal functionality for thunks placed between TorqueScript calls of engine functions and their native 432/// implementations. 433/// 434/// @note The functionality in this group is specific to the console interop system. 435/// @{ 436 437 438// Helper function to return data from a thunk. 439template< typename T > 440inline const char* _EngineConsoleThunkReturnValue( const T& value ) 441{ 442 return EngineMarshallData( value ); 443} 444 445inline bool _EngineConsoleThunkReturnValue( bool value ) 446{ 447 return value; 448} 449inline S32 _EngineConsoleThunkReturnValue( S32 value ) 450{ 451 return value; 452} 453inline F32 _EngineConsoleThunkReturnValue( F32 value ) 454{ 455 return value; 456} 457inline const char* _EngineConsoleThunkReturnValue( const String& str ) 458{ 459 return Con::getReturnBuffer( str ); 460} 461inline const char* _EngineConsoleThunkReturnValue( const char* value ) 462{ 463 return EngineMarshallData( value ); 464} 465template< typename T > 466inline const char* _EngineConsoleThunkReturnValue( T* value ) 467{ 468 return ( value ? value->getIdString() : "" ); 469} 470template< typename T > 471inline const char* _EngineConsoleThunkReturnValue( const T* value ) 472{ 473 return ( value ? value->getIdString() : "" ); 474} 475 476 477 478// Helper class to determine the type of callback registered with the console system. 479template< typename R > 480struct _EngineConsoleThunkType 481{ 482 typedef const char* ReturnType; 483 typedef StringCallback CallbackType; 484}; 485template<> 486struct _EngineConsoleThunkType< S32 > 487{ 488 typedef S32 ReturnType; 489 typedef IntCallback CallbackType; 490}; 491template<> 492struct _EngineConsoleThunkType< U32 > 493{ 494 typedef U32 ReturnType; 495 typedef IntCallback CallbackType; 496}; 497template<> 498struct _EngineConsoleThunkType< F32 > 499{ 500 typedef F32 ReturnType; 501 typedef FloatCallback CallbackType; 502}; 503template<> 504struct _EngineConsoleThunkType< bool > 505{ 506 typedef bool ReturnType; 507 typedef BoolCallback CallbackType; 508}; 509template<> 510struct _EngineConsoleThunkType< void > 511{ 512 typedef void ReturnType; 513 typedef VoidCallback CallbackType; 514}; 515 516 517// Helper struct to count the number of parameters in a function list. 518// The setup through operator () allows omitting the the argument list entirely. 519struct _EngineConsoleThunkCountArgs 520{ 521 522 template<typename ...ArgTs> U32 operator()(ArgTs... args){ 523 return sizeof...(ArgTs); 524 } 525 526 operator U32() const{ // FIXME: WHAT IS THIS?? I'm pretty sure it's incorrect, and it's the version that is invoked by all the macros 527 return 0; 528 } 529}; 530 531 532 533 534// Encapsulation of a legacy console function invocation. 535namespace engineAPI{ 536 namespace detail{ 537 template<S32 startArgc, typename R, typename ...ArgTs> 538 struct ThunkHelpers { 539 using SelfType = ThunkHelpers<startArgc, R, ArgTs...>; 540 using FunctionType = R(*)(ArgTs...); 541 template<typename Frame> using MethodType = R(Frame::*)(ArgTs ...) const; 542 template<size_t I> using IthArgType = typename std::tuple_element<I, std::tuple<ArgTs ...> >::type; 543 544 template<size_t ...> struct Seq {}; 545 template<size_t N, size_t ...S> struct Gens : Gens<N-1, N-1, S...> {}; 546 template<size_t ...I> struct Gens<0, I...>{ typedef Seq<I...> type; }; 547 548 typedef typename _EngineConsoleThunkType< R >::ReturnType ReturnType; 549 static const S32 NUM_ARGS = sizeof...(ArgTs) + startArgc; 550 551 template<size_t index, size_t method_offset = 0, typename ...RealArgTs> 552 static IthArgType<index> getRealArgValue(S32 argc, ConsoleValueRef *argv, const _EngineFunctionDefaultArguments< void(RealArgTs...) >& defaultArgs) 553 { 554 if((startArgc + index) < argc) 555 { 556 return EngineUnmarshallData< IthArgType<index> >()( argv[ startArgc + index ] ); 557 } else { 558 return fixed_tuple_accessor<index + method_offset>::get(defaultArgs.mArgs); 559 } 560 } 561 562 template<size_t ...I> 563 static R dispatchHelper(S32 argc, ConsoleValueRef *argv, FunctionType fn, const _EngineFunctionDefaultArguments< void(ArgTs...) >& defaultArgs, Seq<I...>){ 564 return fn(SelfType::getRealArgValue<I>(argc, argv, defaultArgs) ...); 565 } 566 567 template<typename Frame, size_t ...I> 568 static R dispatchHelper(S32 argc, ConsoleValueRef *argv, MethodType<Frame> fn, Frame* frame, const _EngineFunctionDefaultArguments< void( typename Frame::ObjectType*, ArgTs...) >& defaultArgs, Seq<I...>){ 569 return (frame->*fn)(SelfType::getRealArgValue<I,1>(argc, argv, defaultArgs) ...); 570 } 571 572 using SeqType = typename Gens<sizeof...(ArgTs)>::type; 573 }; 574 575 template<typename ArgVT> struct MarshallHelpers { 576 template<typename ...ArgTs> static void marshallEach(S32 &argc, ArgVT *argv, const ArgTs& ...args){} 577 template<typename H, typename ...Tail> static void marshallEach(S32 &argc, ArgVT *argv, const H& head, const Tail& ...tail){ 578 argv[argc++] = EngineMarshallData(head); 579 marshallEach(argc, argv, tail...); 580 } 581 }; 582 583 template<> struct MarshallHelpers<ConsoleValueRef> { 584 template<typename ...ArgTs> static void marshallEach(S32 &argc, ConsoleValueRef *argv, const ArgTs& ...args){} 585 template<typename H, typename ...Tail> static void marshallEach(S32 &argc, ConsoleValueRef *argv, const H& head, const Tail& ...tail){ 586 EngineMarshallData(head, argc, argv); 587 marshallEach(argc, argv, tail...); 588 } 589 }; 590 } 591} 592 593template< S32 startArgc, typename T > 594struct _EngineConsoleThunk {}; 595 596template< S32 startArgc, typename R, typename ...ArgTs > 597struct _EngineConsoleThunk< startArgc, R(ArgTs...) > 598{ 599private: 600 using Helper = engineAPI::detail::ThunkHelpers<startArgc, R, ArgTs...>; 601 using SeqType = typename Helper::SeqType; 602public: 603 typedef typename Helper::FunctionType FunctionType; 604 typedef typename Helper::ReturnType ReturnType; 605 template<typename Frame> using MethodType = typename Helper::template MethodType<Frame>; 606 static const S32 NUM_ARGS = Helper::NUM_ARGS; 607 608 static ReturnType thunk( S32 argc, ConsoleValueRef *argv, FunctionType fn, const _EngineFunctionDefaultArguments< void(ArgTs...) >& defaultArgs) 609 { 610 return _EngineConsoleThunkReturnValue( Helper::dispatchHelper(argc, argv, fn, defaultArgs, SeqType())); 611 } 612 template< typename Frame > 613 static ReturnType thunk( S32 argc, ConsoleValueRef *argv, MethodType<Frame> fn, Frame* frame, const _EngineFunctionDefaultArguments< void( typename Frame::ObjectType*, ArgTs...) >& defaultArgs) 614 { 615 return _EngineConsoleThunkReturnValue( Helper::dispatchHelper(argc, argv, fn, frame, defaultArgs, SeqType())); 616 } 617}; 618 619// Have to do a partial specialization for void-returning functions :( 620template<S32 startArgc, typename ...ArgTs> 621struct _EngineConsoleThunk<startArgc, void(ArgTs...)> { 622private: 623 using Helper = engineAPI::detail::ThunkHelpers<startArgc, void, ArgTs...>; 624 using SeqType = typename Helper::SeqType; 625public: 626 typedef typename Helper::FunctionType FunctionType; 627 typedef typename Helper::ReturnType ReturnType; 628 template<typename Frame> using MethodType = typename Helper::template MethodType<Frame>; 629 static const S32 NUM_ARGS = Helper::NUM_ARGS; 630 631 static void thunk( S32 argc, ConsoleValueRef *argv, FunctionType fn, const _EngineFunctionDefaultArguments< void(ArgTs...) >& defaultArgs) 632 { 633 Helper::dispatchHelper(argc, argv, fn, defaultArgs, SeqType()); 634 } 635 template< typename Frame > 636 static void thunk( S32 argc, ConsoleValueRef *argv, MethodType<Frame> fn, Frame* frame, const _EngineFunctionDefaultArguments< void( typename Frame::ObjectType*, ArgTs...) >& defaultArgs) 637 { 638 Helper::dispatchHelper(argc, argv, fn, frame, defaultArgs, SeqType()); 639 } 640}; 641 642 643/// @} 644 645/// @name API Definition Macros 646/// 647/// The macros in this group allow to create engine API functions that work both with the 648/// legacy console system as well as with the new engine export system. As such, they only 649/// support those function features that are available in both systems. This means that for 650/// console-style variadic functions, the ConsoleXXX must be used and that for overloaded 651/// and/or C-style variadic functions as well as for placing functions in export scopes, 652/// DEFINE_CALLIN must be used directly. 653/// 654/// When the console system is removed, the console thunking functionality will be removed 655/// from these macros but otherwise they will remain unchanged and in place. 656/// 657/// @{ 658 659 660// Helpers to implement initialization checks. Pulled out into separate macros so this can be deactivated easily. 661// Especially important for the initialize() function itself. 662 663#define _CHECK_ENGINE_INITIALIZED_IMPL( fnName, returnType ) \ 664 if( !engineAPI::gIsInitialized ) \ 665 { \ 666 Con::errorf( "EngineAPI: Engine not initialized when calling " #fnName ); \ 667 return EngineTypeTraits< returnType >::ReturnValue( EngineTypeTraits< returnType >::ReturnValueType() ); \ 668 } 669 670#define _CHECK_ENGINE_INITIALIZED( fnName, returnType ) _CHECK_ENGINE_INITIALIZED_IMPL( fnName, returnType ) 671 672 673/// Define a call-in point for calling into the engine. 674/// 675/// @param name The name of the function as it should be seen by the control layer. 676/// @param returnType The value type returned to the control layer. 677/// @param args The argument list as it would appear on the function definition 678/// @param defaultArgs The list of default argument values. 679/// @param usage The usage doc string for the engine API reference. 680/// 681/// @code 682/// DefineEngineFunction( myFunction, int, ( float f, const String& s ), ( "value for s" ), "This is my function." ) 683/// { 684/// return int( f ) + dAtoi( s ); 685/// } 686/// @endcode 687#define DefineEngineFunction( name, returnType, args, defaultArgs, usage ) \ 688 static inline returnType _fn ## name ## impl args; \ 689 TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## name \ 690 ( _EngineFunctionTrampoline< returnType args >::Args a ) \ 691 { \ 692 _CHECK_ENGINE_INITIALIZED( name, returnType ); \ 693 return EngineTypeTraits< returnType >::ReturnValue( \ 694 _EngineFunctionTrampoline< returnType args >::jmp( _fn ## name ## impl, a ) \ 695 ); \ 696 } \ 697 static _EngineFunctionDefaultArguments< void args > _fn ## name ## DefaultArgs defaultArgs; \ 698 static EngineFunctionInfo _fn ## name ## FunctionInfo( \ 699 #name, \ 700 &_SCOPE<>()(), \ 701 usage, \ 702 #returnType " " #name #args, \ 703 "fn" #name, \ 704 TYPE< returnType args >(), \ 705 &_fn ## name ## DefaultArgs, \ 706 ( void* ) &fn ## name, \ 707 0 \ 708 ); \ 709 static _EngineConsoleThunkType< returnType >::ReturnType _ ## name ## caster( SimObject*, S32 argc, ConsoleValueRef *argv ) \ 710 { \ 711 return _EngineConsoleThunkType< returnType >::ReturnType( _EngineConsoleThunk< 1, returnType args >::thunk( \ 712 argc, argv, &_fn ## name ## impl, _fn ## name ## DefaultArgs \ 713 ) ); \ 714 } \ 715 static ConsoleFunctionHeader _ ## name ## header \ 716 ( #returnType, #args, #defaultArgs ); \ 717 static ConsoleConstructor \ 718 _ ## name ## obj( NULL, #name, _EngineConsoleThunkType< returnType >::CallbackType( _ ## name ## caster ), usage, \ 719 _EngineConsoleThunk< 1, returnType args >::NUM_ARGS - _EngineConsoleThunkCountArgs() defaultArgs, \ 720 _EngineConsoleThunk< 1, returnType args >::NUM_ARGS, \ 721 false, &_ ## name ## header \ 722 ); \ 723 static inline returnType _fn ## name ## impl args 724 725 726// The next thing is a bit tricky. DefineEngineMethod allows to make the 'object' (=this) argument to the function 727// implicit which presents quite an obstacle for the macro internals as the engine export system requires the 728// name of a DLL symbol that represents an extern "C" function with an explicit first object pointer argument. 729// 730// Even if we ignored the fact that we don't have a guarantee how the various C++ compilers implement implicit 'this' arguments, 731// we could still not just use a C++ method for this as then we would have to get past the C++ compiler's mangling to 732// get to the function symbol name (let alone the fact that typing this method correctly would be tricky). 733// 734// So, the trick employed here is to package all but the implicit 'this' argument in a structure and then define an 735// extern "C" function that takes the object pointer as a first argument and the struct type as the second argument. 736// This will result in a function with an identical stack call frame layout to the function we want. 737// 738// Unfortunately, that still requires that function to chain on to the real user-defined function. To do this 739// cleanly and portably, _EngineMethodTrampoline is used to unpack and jump the call from extern "C" into C++ space. 740// In optimized builds, the compiler should be smart enough to pretty much optimize all our trickery here away. 741 742#define _DefineMethodTrampoline( className, name, returnType, args ) \ 743 TORQUE_API EngineTypeTraits< returnType >::ReturnValueType \ 744 fn ## className ## _ ## name ( className* object, _EngineMethodTrampoline< _ ## className ## name ## frame, returnType args >::Args a )\ 745 { \ 746 _CHECK_ENGINE_INITIALIZED( className::name, returnType ); \ 747 return EngineTypeTraits< returnType >::ReturnValue( \ 748 _EngineMethodTrampoline< _ ## className ## name ## frame, returnType args >::jmp( object, a ) \ 749 ); \ 750 } 751 752 753/// Define a call-in point for calling a method on an engine object. 754/// 755/// @param name The name of the C++ class. 756/// @param name The name of the method as it should be seen by the control layer. 757/// @param returnType The value type returned to the control layer. 758/// @param args The argument list as it would appear on the function definition 759/// @param defaultArgs The list of default argument values. 760/// @param usage The usage doc string for the engine API reference. 761/// 762/// @code 763/// DefineEngineMethod( MyClass, myMethod, int, ( float f, const String& s ), ( "value for s" ), "This is my method." ) 764/// { 765/// return object->someMethod( f, s ); 766/// } 767/// @endcode 768#define DefineEngineMethod( className, name, returnType, args, defaultArgs, usage ) \ 769 struct _ ## className ## name ## frame \ 770 { \ 771 typedef className ObjectType; \ 772 className* object; \ 773 inline returnType _exec args const; \ 774 }; \ 775 _DefineMethodTrampoline( className, name, returnType, args ); \ 776 static _EngineFunctionDefaultArguments< _EngineMethodTrampoline< _ ## className ## name ## frame, void args >::FunctionType > \ 777 _fn ## className ## name ## DefaultArgs defaultArgs; \ 778 static EngineFunctionInfo _fn ## className ## name ## FunctionInfo( \ 779 #name, \ 780 &_SCOPE< className >()(), \ 781 usage, \ 782 "virtual " #returnType " " #name #args, \ 783 "fn" #className "_" #name, \ 784 TYPE< _EngineMethodTrampoline< _ ## className ## name ## frame, returnType args >::FunctionType >(), \ 785 &_fn ## className ## name ## DefaultArgs, \ 786 ( void* ) &fn ## className ## _ ## name, \ 787 0 \ 788 ); \ 789 static _EngineConsoleThunkType< returnType >::ReturnType _ ## className ## name ## caster( SimObject* object, S32 argc, ConsoleValueRef *argv ) \ 790 { \ 791 _ ## className ## name ## frame frame; \ 792 frame.object = static_cast< className* >( object ); \ 793 return _EngineConsoleThunkType< returnType >::ReturnType( _EngineConsoleThunk< 2, returnType args >::thunk( \ 794 argc, argv, &_ ## className ## name ## frame::_exec, &frame, _fn ## className ## name ## DefaultArgs \ 795 ) ); \ 796 } \ 797 static ConsoleFunctionHeader _ ## className ## name ## header \ 798 ( #returnType, #args, #defaultArgs ); \ 799 static ConsoleConstructor \ 800 className ## name ## obj( #className, #name, \ 801 _EngineConsoleThunkType< returnType >::CallbackType( _ ## className ## name ## caster ), usage, \ 802 _EngineConsoleThunk< 2, returnType args >::NUM_ARGS - _EngineConsoleThunkCountArgs() defaultArgs, \ 803 _EngineConsoleThunk< 2, returnType args >::NUM_ARGS, \ 804 false, &_ ## className ## name ## header \ 805 ); \ 806 returnType _ ## className ## name ## frame::_exec args const 807 808 809/// Define a call-in point for calling into the engine. Unlike with DefineEngineFunction, the statically 810/// callable function will be confined to the namespace of the given class. 811/// 812/// @param classname The name of the C++ class (or a registered export scope). 813/// @param name The name of the method as it should be seen by the control layer. 814/// @param returnType The value type returned to the control layer. 815/// @param args The argument list as it would appear on the function definition 816/// @param defaultArgs The list of default argument values. 817/// @param usage The usage doc string for the engine API reference. 818/// 819/// @code 820/// DefineEngineStaticMethod( MyClass, myMethod, int, ( float f, string s ), ( "value for s" ), "This is my method." ) 821/// { 822/// } 823/// @endcode 824#define DefineEngineStaticMethod( className, name, returnType, args, defaultArgs, usage ) \ 825 static inline returnType _fn ## className ## name ## impl args; \ 826 TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## className ## _ ## name \ 827 ( _EngineFunctionTrampoline< returnType args >::Args a ) \ 828 { \ 829 _CHECK_ENGINE_INITIALIZED( className::name, returnType ); \ 830 return EngineTypeTraits< returnType >::ReturnValue( \ 831 _EngineFunctionTrampoline< returnType args >::jmp( _fn ## className ## name ## impl, a ) \ 832 ); \ 833 } \ 834 static _EngineFunctionDefaultArguments< void args > _fn ## className ## name ## DefaultArgs defaultArgs; \ 835 static EngineFunctionInfo _fn ## name ## FunctionInfo( \ 836 #name, \ 837 &_SCOPE< className >()(), \ 838 usage, \ 839 #returnType " " #name #args, \ 840 "fn" #className "_" #name, \ 841 TYPE< returnType args >(), \ 842 &_fn ## className ## name ## DefaultArgs, \ 843 ( void* ) &fn ## className ## _ ## name, \ 844 0 \ 845 ); \ 846 static _EngineConsoleThunkType< returnType >::ReturnType _ ## className ## name ## caster( SimObject*, S32 argc, ConsoleValueRef *argv )\ 847 { \ 848 return _EngineConsoleThunkType< returnType >::ReturnType( _EngineConsoleThunk< 1, returnType args >::thunk( \ 849 argc, argv, &_fn ## className ## name ## impl, _fn ## className ## name ## DefaultArgs \ 850 ) ); \ 851 } \ 852 static ConsoleFunctionHeader _ ## className ## name ## header \ 853 ( #returnType, #args, #defaultArgs, true ); \ 854 static ConsoleConstructor \ 855 _ ## className ## name ## obj( #className, #name, _EngineConsoleThunkType< returnType >::CallbackType( _ ## className ## name ## caster ), usage, \ 856 _EngineConsoleThunk< 1, returnType args >::NUM_ARGS - _EngineConsoleThunkCountArgs() defaultArgs, \ 857 _EngineConsoleThunk< 1, returnType args >::NUM_ARGS, \ 858 false, &_ ## className ## name ## header \ 859 ); \ 860 static inline returnType _fn ## className ## name ## impl args 861 862# define DefineEngineStringlyVariadicFunction(name,returnType,minArgs,maxArgs,usage) \ 863 static inline returnType _fn ## name ## impl (SimObject *, S32 argc, ConsoleValueRef *argv); \ 864 TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## name \ 865 (Vector<const char*>* vec) \ 866 { \ 867 _CHECK_ENGINE_INITIALIZED( name, returnType ); \ 868 StringStackConsoleWrapper args(vec->size(), vec->address()); \ 869 return EngineTypeTraits< returnType >::ReturnValue( \ 870 _fn ## name ## impl(NULL, args.count(), args) \ 871 ); \ 872 } \ 873 static _EngineFunctionDefaultArguments< void (Vector<const char*>* vec) > _fn ## name ## DefaultArgs; \ 874 static EngineFunctionInfo _fn ## name ## FunctionInfo( \ 875 #name, \ 876 &_SCOPE<>()(), \ 877 usage, \ 878 #returnType " " #name "(Vector<String> args)", \ 879 "fn" #name, \ 880 TYPE< returnType (Vector<const char*>* vec) >(), \ 881 &_fn ## name ## DefaultArgs, \ 882 ( void* ) &fn ## name, \ 883 0 \ 884 ); \ 885 ConsoleConstructor cc_##name##_obj(NULL,#name,_fn ## name ## impl,usage,minArgs,maxArgs); \ 886 returnType _fn ## name ## impl(SimObject *, S32 argc, ConsoleValueRef *argv) 887 888# define DefineEngineStringlyVariadicMethod(className, name,returnType,minArgs,maxArgs,usage) \ 889 struct _ ## className ## name ## frame \ 890 { \ 891 typedef className ObjectType; \ 892 className* object; \ 893 inline returnType _exec (S32 argc, ConsoleValueRef* argv) const; \ 894 }; \ 895 TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## className ## _ ## name \ 896 (className* object, Vector<const char*>* vec) \ 897 { \ 898 _CHECK_ENGINE_INITIALIZED( name, returnType ); \ 899 StringStackConsoleWrapper args(vec->size(), vec->address()); \ 900 _ ## className ## name ## frame frame {}; \ 901 frame.object = static_cast< className* >( object ); \ 902 return EngineTypeTraits< returnType >::ReturnValue( \ 903 frame._exec(args.count(), args) \ 904 ); \ 905 } \ 906 static _EngineFunctionDefaultArguments< void (className* object, S32 argc, const char** argv) > \ 907 _fn ## className ## name ## DefaultArgs; \ 908 static EngineFunctionInfo _fn ## className ## name ## FunctionInfo( \ 909 #name, \ 910 &_SCOPE< className >()(), \ 911 usage, \ 912 "virtual " #returnType " " #name "(Vector<String> args)", \ 913 "fn" #className "_" #name, \ 914 TYPE< _EngineMethodTrampoline< _ ## className ## name ## frame, returnType (Vector<const char*> vec) >::FunctionType >(), \ 915 &_fn ## className ## name ## DefaultArgs, \ 916 ( void* ) &fn ## className ## _ ## name, \ 917 0 \ 918 ); \ 919 returnType cm_##className##_##name##_caster(SimObject* object, S32 argc, ConsoleValueRef* argv) { \ 920 AssertFatal( dynamic_cast<className*>( object ), "Object passed to " #name " is not a " #className "!" ); \ 921 _ ## className ## name ## frame frame {}; \ 922 frame.object = static_cast< className* >( object ); \ 923 conmethod_return_##returnType ) frame._exec(argc,argv); \ 924 }; \ 925 ConsoleConstructor cc_##className##_##name##_obj(#className,#name,cm_##className##_##name##_caster,usage,minArgs,maxArgs); \ 926 inline returnType _ ## className ## name ## frame::_exec(S32 argc, ConsoleValueRef *argv) const 927 928 929 930// The following three macros are only temporary. They allow to define engineAPI functions using the framework 931// here in this file while being visible only in the new API. When the console interop is removed, these macros 932// can be removed and all their uses be replaced with their corresponding versions that now still include support 933// for the console (e.g. DefineNewEngineFunction should become DefineEngineFunction). 934#define DefineNewEngineFunction( name, returnType, args, defaultArgs, usage ) \ 935 static inline returnType _fn ## name ## impl args; \ 936 TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## name \ 937 ( _EngineFunctionTrampoline< returnType args >::Args a ) \ 938 { \ 939 _CHECK_ENGINE_INITIALIZED( name, returnType ); \ 940 return EngineTypeTraits< returnType >::ReturnValue( \ 941 _EngineFunctionTrampoline< returnType args >::jmp( _fn ## name ## impl, a ) \ 942 ); \ 943 } \ 944 static _EngineFunctionDefaultArguments< void args > _fn ## name ## DefaultArgs defaultArgs; \ 945 static EngineFunctionInfo _fn ## name ## FunctionInfo( \ 946 #name, \ 947 &_SCOPE<>()(), \ 948 usage, \ 949 #returnType " " #name #args, \ 950 "fn" #name, \ 951 TYPE< returnType args >(), \ 952 &_fn ## name ## DefaultArgs, \ 953 ( void* ) &fn ## name, \ 954 0 \ 955 ); \ 956 static inline returnType _fn ## name ## impl args 957 958#define DefineNewEngineMethod( className, name, returnType, args, defaultArgs, usage ) \ 959 struct _ ## className ## name ## frame \ 960 { \ 961 typedef className ObjectType; \ 962 className* object; \ 963 inline returnType _exec args const; \ 964 }; \ 965 _DefineMethodTrampoline( className, name, returnType, args ); \ 966 static _EngineFunctionDefaultArguments< _EngineMethodTrampoline< _ ## className ## name ## frame, void args >::FunctionType > \ 967 _fn ## className ## name ## DefaultArgs defaultArgs; \ 968 static EngineFunctionInfo _fn ## className ## name ## FunctionInfo( \ 969 #name, \ 970 &_SCOPE< className >()(), \ 971 usage, \ 972 "virtual " #returnType " " #name #args, \ 973 "fn" #className "_" #name, \ 974 TYPE< _EngineMethodTrampoline< _ ## className ## name ## frame, returnType args >::FunctionType >(), \ 975 &_fn ## className ## name ## DefaultArgs, \ 976 ( void* ) &fn ## className ## _ ## name, \ 977 0 \ 978 ); \ 979 returnType _ ## className ## name ## frame::_exec args const 980 981#define DefineNewEngineStaticMethod( className, name, returnType, args, defaultArgs, usage ) \ 982 static inline returnType _fn ## className ## name ## impl args; \ 983 TORQUE_API EngineTypeTraits< returnType >::ReturnValueType fn ## className ## _ ## name \ 984 ( _EngineFunctionTrampoline< returnType args >::Args a ) \ 985 { \ 986 _CHECK_ENGINE_INITIALIZED( className::name, returnType ); \ 987 return EngineTypeTraits< returnType >::ReturnValue( \ 988 _EngineFunctionTrampoline< returnType args >::jmp( _fn ## className ## name ## impl, a ) \ 989 ); \ 990 } \ 991 static _EngineFunctionDefaultArguments< void args > _fn ## className ## name ## DefaultArgs defaultArgs; \ 992 static EngineFunctionInfo _fn ## name ## FunctionInfo( \ 993 #name, \ 994 &_SCOPE< className >()(), \ 995 usage, \ 996 #returnType " " #name #args, \ 997 "fn" #className "_" #name, \ 998 TYPE< returnType args >(), \ 999 &_fn ## className ## name ## DefaultArgs, \ 1000 ( void* ) &fn ## className ## _ ## name, \ 1001 0 \ 1002 ); \ 1003 static inline returnType _fn ## className ## name ## impl args 1004 1005/// @} 1006 1007 1008//============================================================================= 1009// Callbacks. 1010//============================================================================= 1011 1012/// Matching implement for DECLARE_CALLBACK. 1013/// 1014/// 1015/// @warn With the new interop system, method-style callbacks <em>must not</em> be triggered on object 1016/// that are being created! This is because the control layer will likely not yet have a fully valid wrapper 1017/// object in place for the EngineObject under construction. 1018#define IMPLEMENT_CALLBACK( class, name, returnType, args, argNames, usageString ) \ 1019 struct _ ## class ## name ## frame { typedef class ObjectType; }; \ 1020 TORQUE_API _EngineMethodTrampoline< _ ## class ## name ## frame, returnType args >::FunctionType* cb ## class ## _ ## name; \ 1021 TORQUE_API void set_cb ## class ## _ ## name( \ 1022 _EngineMethodTrampoline< _ ## class ## name ## frame, returnType args >::FunctionType fn ) \ 1023 { cb ## class ## _ ## name = fn; } \ 1024 _EngineMethodTrampoline< _ ## class ## name ## frame, returnType args >::FunctionType* cb ## class ## _ ## name; \ 1025 namespace { \ 1026 ::EngineFunctionInfo _cb ## class ## name( \ 1027 #name, \ 1028 &::_SCOPE< class >()(), \ 1029 usageString, \ 1030 "virtual " #returnType " " #name #args, \ 1031 "cb" #class "_" #name, \ 1032 ::TYPE< _EngineMethodTrampoline< _ ## class ## name ## frame, returnType args >::FunctionType >(), \ 1033 NULL, \ 1034 ( void* ) &cb ## class ## _ ## name, \ 1035 EngineFunctionCallout \ 1036 ); \ 1037 } \ 1038 returnType class::name ## _callback args \ 1039 { \ 1040 if( cb ## class ## _ ## name ) { \ 1041 _EngineCallbackHelper cbh( this, reinterpret_cast< const void* >( cb ## class ## _ ## name ) ); \ 1042 return returnType( cbh.call< returnType > argNames ); \ 1043 } \ 1044 if( engineAPI::gUseConsoleInterop ) \ 1045 { \ 1046 static StringTableEntry sName = StringTable->insert( #name ); \ 1047 _EngineConsoleCallbackHelper cbh( sName, this ); \ 1048 return returnType( cbh.call< returnType > argNames ); \ 1049 } \ 1050 return returnType(); \ 1051 } \ 1052 namespace { \ 1053 ConsoleFunctionHeader _ ## class ## name ## header( \ 1054 #returnType, #args, "" ); \ 1055 ConsoleConstructor _ ## class ## name ## obj( #class, #name, usageString, &_ ## class ## name ## header ); \ 1056 } 1057 1058 1059/// Used to define global callbacks not associated with 1060/// any particular class or namespace. 1061#define IMPLEMENT_GLOBAL_CALLBACK( name, returnType, args, argNames, usageString ) \ 1062 DEFINE_CALLOUT( cb ## name, name,, returnType, args, 0, usageString ); \ 1063 returnType name ## _callback args \ 1064 { \ 1065 if( cb ## name ) \ 1066 return returnType( cb ## name argNames ); \ 1067 if( engineAPI::gUseConsoleInterop ) \ 1068 { \ 1069 static StringTableEntry sName = StringTable->insert( #name ); \ 1070 _EngineConsoleCallbackHelper cbh( sName, NULL ); \ 1071 return returnType( cbh.call< returnType > argNames ); \ 1072 } \ 1073 return returnType(); \ 1074 } \ 1075 namespace { \ 1076 ConsoleFunctionHeader _ ## name ## header( \ 1077 #returnType, #args, "" ); \ 1078 ConsoleConstructor _ ## name ## obj( NULL, #name, usageString, &_ ## name ## header ); \ 1079 } 1080 1081 1082// Again, temporary macros to allow splicing the API while we still have the console interop around. 1083 1084#define IMPLEMENT_CONSOLE_CALLBACK( class, name, returnType, args, argNames, usageString ) \ 1085 returnType class::name ## _callback args \ 1086 { \ 1087 if( engineAPI::gUseConsoleInterop ) \ 1088 { \ 1089 static StringTableEntry sName = StringTable->insert( #name ); \ 1090 _EngineConsoleCallbackHelper cbh( sName, this ); \ 1091 return returnType( cbh.call< returnType > argNames ); \ 1092 } \ 1093 return returnType(); \ 1094 } \ 1095 namespace { \ 1096 ConsoleFunctionHeader _ ## class ## name ## header( \ 1097 #returnType, #args, "" ); \ 1098 ConsoleConstructor _ ## class ## name ## obj( #class, #name, usageString, &_ ## class ## name ## header ); \ 1099 } 1100 1101#define IMPLEMENT_NEW_CALLBACK( class, name, returnType, args, argNames, usageString ) \ 1102 struct _ ## class ## name ## frame { typedef class ObjectType; }; \ 1103 TORQUE_API _EngineMethodTrampoline< _ ## class ## name ## frame, returnType args >::FunctionType* cb ## class ## _ ## name; \ 1104 TORQUE_API void set_cb ## class ## _ ## name( \ 1105 _EngineMethodTrampoline< _ ## class ## name ## frame, returnType args >::FunctionType fn ) \ 1106 { cb ## class ## _ ## name = fn; } \ 1107 _EngineMethodTrampoline< _ ## class ## name ## frame, returnType args >::FunctionType* cb ## class ## _ ## name; \ 1108 namespace { \ 1109 ::EngineFunctionInfo _cb ## class ## name( \ 1110 #name, \ 1111 &::_SCOPE< class >()(), \ 1112 usageString, \ 1113 "virtual " #returnType " " #name #args, \ 1114 "cb" #class "_" #name, \ 1115 ::TYPE< _EngineMethodTrampoline< _ ## class ## name ## frame, returnType args >::FunctionType >(), \ 1116 NULL, \ 1117 &cb ## class ## _ ## name, \ 1118 EngineFunctionCallout \ 1119 ); \ 1120 } \ 1121 returnType class::name ## _callback args \ 1122 { \ 1123 if( cb ## class ## _ ## name ) { \ 1124 _EngineCallbackHelper cbh( this, reinterpret_cast< const void* >( cb ## class ## _ ## name ) ); \ 1125 return returnType( cbh.call< returnType > argNames ); \ 1126 } \ 1127 return returnType(); \ 1128 } 1129 1130 1131 1132 1133// Internal helper class for doing call-outs in the new interop. 1134struct _EngineCallbackHelper 1135{ 1136 protected: 1137 1138 EngineObject* mThis; 1139 const void* mFn; 1140 1141 public: 1142 1143 _EngineCallbackHelper( EngineObject* pThis, const void* fn ) 1144 : mThis( pThis ), 1145 mFn( fn ) {} 1146 1147 template< typename R, typename ...ArgTs > 1148 R call(ArgTs ...args) const 1149 { 1150 typedef R( FunctionType )( EngineObject*, ArgTs... ); 1151 return R( reinterpret_cast< FunctionType* >( const_cast<void*>(mFn) )( mThis, args... ) ); 1152 } 1153 1154}; 1155 1156 1157#include "console/stringStack.h" 1158 1159// Internal helper for callback support in legacy console system. 1160struct _BaseEngineConsoleCallbackHelper 1161{ 1162public: 1163 1164 /// Matches up to storeArgs. 1165 static const U32 MAX_ARGUMENTS = 11; 1166 1167 SimObject* mThis; 1168 S32 mInitialArgc; 1169 S32 mArgc; 1170 StringTableEntry mCallbackName; 1171 ConsoleValueRef mArgv[ MAX_ARGUMENTS + 2 ]; 1172 1173 ConsoleValueRef _exec(); 1174 ConsoleValueRef _execLater(SimConsoleThreadExecEvent *evt); 1175 1176 _BaseEngineConsoleCallbackHelper(): mThis(NULL), mInitialArgc(0), mArgc(0), mCallbackName(StringTable->EmptyString()){;} 1177}; 1178 1179 1180 1181// Base helper for console callbacks 1182struct _EngineConsoleCallbackHelper : public _BaseEngineConsoleCallbackHelper 1183{ 1184private: 1185 using Helper = engineAPI::detail::MarshallHelpers<ConsoleValueRef>; 1186public: 1187 1188 _EngineConsoleCallbackHelper( StringTableEntry callbackName, SimObject* pThis ) 1189 { 1190 mThis = pThis; 1191 mArgc = mInitialArgc = pThis ? 2 : 1 ; 1192 mCallbackName = callbackName; 1193 } 1194 1195 template< typename R, typename ...ArgTs > 1196 R call(ArgTs ...args) 1197 { 1198 if (Con::isMainThread()) 1199 { 1200 ConsoleStackFrameSaver sav; sav.save(); 1201 CSTK.reserveValues(mArgc + sizeof...(ArgTs), mArgv); 1202 mArgv[ 0 ].value->setStackStringValue(mCallbackName); 1203 1204 Helper::marshallEach(mArgc, mArgv, args...); 1205 1206 return R( EngineUnmarshallData< R>()( _exec() ) ); 1207 } 1208 else 1209 { 1210 SimConsoleThreadExecCallback cb; 1211 SimConsoleThreadExecEvent *evt = new SimConsoleThreadExecEvent(mArgc + sizeof...(ArgTs), NULL, false, &cb); 1212 evt->populateArgs(mArgv); 1213 mArgv[ 0 ].value->setStackStringValue(mCallbackName); 1214 1215 Helper::marshallEach(mArgc, mArgv, args...); 1216 1217 Sim::postEvent((SimObject*)Sim::getRootGroup(), evt, Sim::getCurrentTime()); 1218 1219 return R( EngineUnmarshallData< R>()( cb.waitForResult() ) ); 1220 } 1221 } 1222 1223}; 1224 1225 1226// Override for when first parameter is presumably a SimObject*, in which case A will be absorbed as the callback 1227template<typename P1> struct _EngineConsoleExecCallbackHelper : public _BaseEngineConsoleCallbackHelper 1228{ 1229private: 1230 using Helper = engineAPI::detail::MarshallHelpers<ConsoleValueRef>; 1231public: 1232 1233 _EngineConsoleExecCallbackHelper( SimObject* pThis ) 1234 { 1235 mThis = pThis; 1236 mArgc = mInitialArgc = 2; 1237 mCallbackName = NULL; 1238 } 1239 1240 1241 template< typename R, typename SCB, typename ...ArgTs > 1242 R call( SCB simCB , ArgTs ...args ) 1243 { 1244 if (Con::isMainThread()) 1245 { 1246 ConsoleStackFrameSaver sav; sav.save(); 1247 CSTK.reserveValues(mArgc+sizeof...(ArgTs), mArgv); 1248 mArgv[ 0 ].value->setStackStringValue(simCB); 1249 1250 Helper::marshallEach(mArgc, mArgv, args...); 1251 1252 return R( EngineUnmarshallData< R>()( _exec() ) ); 1253 } 1254 else 1255 { 1256 SimConsoleThreadExecCallback cb; 1257 SimConsoleThreadExecEvent *evt = new SimConsoleThreadExecEvent(mArgc+sizeof...(ArgTs), NULL, true, &cb); 1258 evt->populateArgs(mArgv); 1259 mArgv[ 0 ].value->setStackStringValue(simCB); 1260 1261 Helper::marshallEach(mArgc, mArgv, args...); 1262 1263 Sim::postEvent(mThis, evt, Sim::getCurrentTime()); 1264 1265 return R( EngineUnmarshallData< R>()( cb.waitForResult() ) ); 1266 } 1267 } 1268}; 1269 1270// Override for when first parameter is const char* 1271template<> struct _EngineConsoleExecCallbackHelper<const char*> : public _BaseEngineConsoleCallbackHelper 1272{ 1273private: 1274 using Helper = engineAPI::detail::MarshallHelpers<ConsoleValueRef>; 1275public: 1276 _EngineConsoleExecCallbackHelper( const char *callbackName ) 1277 { 1278 mThis = NULL; 1279 mArgc = mInitialArgc = 1; 1280 mCallbackName = StringTable->insert(callbackName); 1281 } 1282 1283 template< typename R, typename ...ArgTs > 1284 R call(ArgTs ...args) 1285 { 1286 if (Con::isMainThread()) 1287 { 1288 ConsoleStackFrameSaver sav; sav.save(); 1289 CSTK.reserveValues(mArgc+sizeof...(ArgTs), mArgv); 1290 mArgv[ 0 ].value->setStackStringValue(mCallbackName); 1291 1292 Helper::marshallEach(mArgc, mArgv, args...); 1293 1294 return R( EngineUnmarshallData< R>()( _exec() ) ); 1295 } 1296 else 1297 { 1298 SimConsoleThreadExecCallback cb; 1299 SimConsoleThreadExecEvent *evt = new SimConsoleThreadExecEvent(mArgc+sizeof...(ArgTs), NULL, false, &cb); 1300 evt->populateArgs(mArgv); 1301 mArgv[ 0 ].value->setStackStringValue(mCallbackName); 1302 1303 Helper::marshallEach(mArgc, mArgv, args...); 1304 1305 Sim::postEvent((SimObject*)Sim::getRootGroup(), evt, Sim::getCurrentTime()); 1306 return R( EngineUnmarshallData< R>()( cb.waitForResult() ) ); 1307 } 1308 } 1309}; 1310 1311// Re-enable some VC warnings we disabled for this file. 1312#pragma warning( pop ) // 4510 and 4610 1313 1314#endif // !_ENGINEAPI_H_ 1315