engineFunctions.h
Engine/source/console/engineFunctions.h
Structures for function-type engine export information.
Classes:
Structure storing the default argument values for a function invocation frame.
A function exported by the engine for interfacing with the control layer.
Public Defines
DEFINE_CALLIN(bindingName, exportName, scope, returnType, args, defaultArgs, flags, doc) TORQUE_API returnType bindingName args; \ namespace { namespace _ ## bindingName { \ < args > sDefaultArgs defaultArgs; \ sFunctionInfo( \ #exportName, \ &< scope >()(), \ doc, \ #returnType " " #exportName #args, \ #bindingName, \ < returnType args >(), \ &sDefaultArgs, \ ( * ) &bindingName, \ ( flags ) \ ); \ } } \ TORQUE_API returnType bindingName args
Due to the given argument types and return type being directly used as is, it is not possible to use this macro with engine types that have more complex value passing semantics (like e.g.
DEFINE_CALLOUT(bindingName, exportName, scope, returnType, args, flags, doc) TORQUE_API returnType ( *bindingName ) args; \ TORQUE_API set_ ## bindingName( returnType ( *fn ) args ) \ { bindingName = fn; } \ returnType ( *bindingName ) args; \ namespace { \ :: _cb ## bindingName( \ #exportName, \ &::< scope >()(), \ doc, \ #returnType " " #exportName #args, \ #bindingName, \ ::< returnType args >(), \ , \ ( * ) &bindingName, \ | ( flags ) \ ); \ }
Not all control layers may be able to access data variables in a DLL so this macro exposes both the variable and a set_XXX function to set the variable programmatically.
Public Enumerations
EngineFunctionFlags { EngineFunctionCallout = BIT( 0 ) }
Detailed Description
Structures for function-type engine export information.
Public Defines
DEFINE_CALLIN(bindingName, exportName, scope, returnType, args, defaultArgs, flags, doc) TORQUE_API returnType bindingName args; \ namespace { namespace _ ## bindingName { \ < args > sDefaultArgs defaultArgs; \ sFunctionInfo( \ #exportName, \ &< scope >()(), \ doc, \ #returnType " " #exportName #args, \ #bindingName, \ < returnType args >(), \ &sDefaultArgs, \ ( * ) &bindingName, \ ( flags ) \ ); \ } } \ TORQUE_API returnType bindingName args
Due to the given argument types and return type being directly used as is, it is not possible to use this macro with engine types that have more complex value passing semantics (like e.g.
String). Use engineAPI in this case.
note:The method of defining functions exposed by this macro is very low-level. To more conveniently define API functions and methods, use the facilities provided in engineAPI.h.
DEFINE_CALLOUT(bindingName, exportName, scope, returnType, args, flags, doc) TORQUE_API returnType ( *bindingName ) args; \ TORQUE_API set_ ## bindingName( returnType ( *fn ) args ) \ { bindingName = fn; } \ returnType ( *bindingName ) args; \ namespace { \ :: _cb ## bindingName( \ #exportName, \ &::< scope >()(), \ doc, \ #returnType " " #exportName #args, \ #bindingName, \ ::< returnType args >(), \ , \ ( * ) &bindingName, \ | ( flags ) \ ); \ }
Not all control layers may be able to access data variables in a DLL so this macro exposes both the variable and a set_XXX function to set the variable programmatically.
Public Enumerations
EngineFunctionFlags
Enumerator
- EngineFunctionCallout = BIT( 0 )
Function is a callback into the control layer.
If this flag is not set, the function is a call-in.
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 _ENGINEFUNCTIONS_H_ 25#define _ENGINEFUNCTIONS_H_ 26 27#include <tuple> 28 29#ifndef _ENGINEEXPORTS_H_ 30 #include "console/engineExports.h" 31#endif 32#ifndef _ENGINETYPEINFO_H_ 33 #include "console/engineTypeInfo.h" 34#endif 35 36 37/// @file 38/// Structures for function-type engine export information. 39 40 41#ifdef TORQUE_COMPILER_VISUALC 42 #define TORQUE_API extern "C" __declspec( dllexport ) 43#elif defined( TORQUE_COMPILER_GCC ) 44 #define TORQUE_API extern "C" __attribute__( ( visibility( "default" ) ) ) 45#else 46 #error Unsupported compiler. 47#endif 48 49 50// #pragma pack is bugged in GCC in that the packing in place at the template instantiation 51// sites rather than their definition sites is used. Enable workarounds. 52#ifdef TORQUE_COMPILER_GCC 53 #define _PACK_BUG_WORKAROUNDS 54#endif 55 56 57 58/// Structure storing the default argument values for a function invocation 59/// frame. 60struct EngineFunctionDefaultArguments 61{ 62 /// Number of default arguments for the function call frame. 63 /// 64 /// @warn This is @b NOT the size of the memory block returned by getArgs() and also 65 /// not the number of elements it contains. 66 U32 mNumDefaultArgs; 67 68 /// Return a pointer to the variable-sized array of default argument values. 69 /// 70 /// @warn The arguments must be stored @b IMMEDIATELY after #mNumDefaultArgs. 71 /// @warn This is a @b FULL frame and not just the default arguments, i.e. it starts with the 72 /// first argument that the function takes and ends with the last argument it takes. 73 /// @warn If the compiler's #pragma pack is buggy, the elements in this structure are allowed 74 /// to be 4-byte aligned rather than byte-aligned as they should be. 75 const U8* getArgs() const 76 { 77 return ( const U8* ) &( mNumDefaultArgs ) + sizeof( mNumDefaultArgs ); 78 } 79}; 80 81 82// Need byte-aligned packing for the default argument structures. 83#ifdef _WIN64 84#pragma pack( push, 4 ) 85#else 86#pragma pack( push, 1 ) 87#endif 88 89 90// Structure encapsulating default arguments to an engine API function. 91template< typename T > 92struct _EngineFunctionDefaultArguments {}; 93 94template<typename ...ArgTs> 95struct _EngineFunctionDefaultArguments< void(ArgTs...) > : public EngineFunctionDefaultArguments 96{ 97 template<typename T> using DefVST = typename EngineTypeTraits<T>::DefaultArgumentValueStoreType; 98 std::tuple<DefVST<ArgTs> ...> mArgs; 99private: 100 using SelfType = _EngineFunctionDefaultArguments< void(ArgTs...) >; 101 102 template<size_t ...> struct Seq {}; 103 template<size_t N, size_t ...S> struct Gens : Gens<N-1, N-1, S...> {}; 104 105 template<size_t ...I> struct Gens<0, I...>{ typedef Seq<I...> type; }; 106 107 template<typename ...TailTs, size_t ...I> 108 static void copyHelper(std::tuple<DefVST<ArgTs> ...> &args, std::tuple<DefVST<TailTs> ...> &defaultArgs, Seq<I...>) { 109 std::tie(std::get<I + (sizeof...(ArgTs) - sizeof...(TailTs))>(args)...) = defaultArgs; 110 } 111 112#ifdef _MSC_VER == 1910 113 template<typename ...TailTs> 114 struct DodgyVCHelper 115 { 116 using type = typename std::enable_if<sizeof...(TailTs) <= sizeof...(ArgTs), decltype(mArgs)>::type; 117 }; 118 119 template<typename ...TailTs> using MaybeSelfEnabled = typename DodgyVCHelper<TailTs...>::type; 120#else 121 template<typename ...TailTs> using MaybeSelfEnabled = typename std::enable_if<sizeof...(TailTs) <= sizeof...(ArgTs), decltype(mArgs)>::type; 122#endif 123 124 template<typename ...TailTs> static MaybeSelfEnabled<TailTs...> tailInit(TailTs ...tail) { 125 std::tuple<DefVST<ArgTs>...> argsT; 126 std::tuple<DefVST<TailTs>...> tailT = std::make_tuple(tail...); 127 SelfType::copyHelper<TailTs...>(argsT, tailT, typename Gens<sizeof...(TailTs)>::type()); 128 return argsT; 129 }; 130 131public: 132 template<typename ...TailTs> _EngineFunctionDefaultArguments(TailTs ...tail) 133 : EngineFunctionDefaultArguments({sizeof...(TailTs)}), mArgs(SelfType::tailInit(tail...)) 134 {} 135}; 136 137#pragma pack( pop ) 138 139 140// Helper to allow flags argument to DEFINE_FUNCTION to be empty. 141struct _EngineFunctionFlags 142{ 143 U32 val; 144 _EngineFunctionFlags() 145 : val( 0 ) {} 146 _EngineFunctionFlags( U32 val ) 147 : val( val ) {} 148 operator U32() const { return val; } 149}; 150 151 152/// 153enum EngineFunctionFlags 154{ 155 /// Function is a callback into the control layer. If this flag is not set, 156 /// the function is a call-in. 157 EngineFunctionCallout = BIT( 0 ), 158}; 159 160 161/// A function exported by the engine for interfacing with the control layer. 162/// 163/// A function can either be a call-in, transfering control flow from the control layer to the engine, or a call-out, 164/// transfering control flow from the engine to the control layer. 165/// 166/// All engine API functions use the native C (@c cdecl) calling convention. 167/// 168/// Be aware that there a no implicit parameters to functions. This, for example, means that methods will simply 169/// list an object type parameter as their first argument but otherwise be indistinguishable from other functions. 170/// 171/// Variadic functions are supported. 172/// 173/// @section engineFunction_strings String Arguments and Return Values 174/// 175/// Strings passed through the API are assumed to be owned by the caller. They must persist for the entire duration 176/// of a call. 177/// 178/// Strings returned by a function are assumed to be in transient storage that will be overwritten by subsequent API 179/// calls. If the caller wants to preserve a string, it is responsible to copying strings to its own memory. This will 180/// happen with most higher-level control layers anyway. 181/// 182/// @section engineFunction_defaultargs Default Arguments 183/// 184/// As the engine API export system is set up to not require hand-written code in generated wrappers per se, the 185/// export system seeks to include a maximum possible amount of information in the export structures. 186/// To this end, where applicable, information about suggested default values for arguments to the engine API 187/// functions is stored in the export structures. It is up to the wrapper generator if and how it makes use of 188/// this information. 189/// 190/// Default arguments are represented by capturing raw stack frame vectors of the arguments to functions. These 191/// frames could be used as default images for passing arguments in stack frames, though wrapper generators 192/// may actually want to read out individual argument values and include them in function prototypes within 193/// the generated code. 194/// 195/// @section engineFunction_callin Call-ins 196/// 197/// Call-ins are exposed as native entry points. The control layer must be able to natively 198/// marshall arguments and call DLL function exports using C calling conventions. 199/// 200/// @section engineFunction_callout Call-outs 201/// 202/// Call-outs are exposed as pointer-sized memory locations into which the control layer needs 203/// to install addresses of functions that receive the call from the engine back into the control 204/// layer. The function has to follow C calling conventions and 205/// 206/// A call-out will initially be set to NULL and while being NULL, will simply cause the engine 207/// to skip and ignore the call-out. This allows the control layer to only install call-outs 208/// it is actually interested in. 209/// 210class EngineFunctionInfo : public EngineExport 211{ 212 public: 213 214 DECLARE_CLASS( EngineFunctionInfo, EngineExport ); 215 216 protected: 217 218 /// A combination of EngineFunctionFlags. 219 BitSet32 mFunctionFlags; 220 221 /// The type of the function. 222 const EngineTypeInfo* mFunctionType; 223 224 /// Default values for the function arguments. 225 const EngineFunctionDefaultArguments* mDefaultArgumentValues; 226 227 /// Name of the DLL symbol denoting the address of the exported entity. 228 const char* mBindingName; 229 230 /// Full function prototype string. Useful for quick printing and most importantly, 231 /// this will be the only place containing information about the argument names. 232 const char* mPrototypeString; 233 234 /// Address of either the function implementation or the variable taking the address 235 /// of a call-out. 236 void* mAddress; 237 238 /// Next function in the global link chain of engine functions. 239 EngineFunctionInfo* mNextFunction; 240 241 /// First function in the global link chain of engine functions. 242 static EngineFunctionInfo* smFirstFunction; 243 244 public: 245 246 /// 247 EngineFunctionInfo( const char* name, 248 EngineExportScope* scope, 249 const char* docString, 250 const char* protoypeString, 251 const char* bindingName, 252 const EngineTypeInfo* functionType, 253 const EngineFunctionDefaultArguments* defaultArgs, 254 void* address, 255 U32 flags ); 256 257 /// Return the name of the function. 258 const char* getFunctionName() const { return getExportName(); } 259 260 /// Return the function's full prototype string including the return type, function name, 261 /// and argument list. 262 const char* getPrototypeString() const { return mPrototypeString; } 263 264 /// Return the DLL export symbol name. 265 const char* getBindingName() const { return mBindingName; } 266 267 /// Test whether this is a callout function. 268 bool isCallout() const { return mFunctionFlags.test( EngineFunctionCallout ); } 269 270 /// Test whether the function is variadic, i.e. takes a variable number of arguments. 271 bool isVariadic() const { return mFunctionType->isVariadic(); } 272 273 /// Return the type of this function. 274 const EngineTypeInfo* getFunctionType() const { return mFunctionType; } 275 276 /// Return the return type of the function. 277 const EngineTypeInfo* getReturnType() const { return getFunctionType()->getArgumentTypeTable()->getReturnType(); } 278 279 /// Return the number of arguments that this function takes. If the function is variadic, 280 /// this is the number of fixed arguments. 281 U32 getNumArguments() const { return getFunctionType()->getArgumentTypeTable()->getNumArguments(); } 282 283 /// 284 const EngineTypeInfo* getArgumentType( U32 index ) const { return ( *( getFunctionType()->getArgumentTypeTable() ) )[ index ]; } 285 286 /// Return the vector storing the default argument values. 287 const EngineFunctionDefaultArguments* getDefaultArguments() const { return mDefaultArgumentValues; } 288 289 /// Reset all callout function pointers back to NULL. This deactivates all callbacks. 290 static void resetAllCallouts(); 291}; 292 293 294/// 295/// 296/// Due to the given argument types and return type being directly used as is, it is not possible 297/// to use this macro with engine types that have more complex value passing semantics (like e.g. 298/// String). Use engineAPI in this case. 299/// 300/// @note The method of defining functions exposed by this macro is very low-level. To more 301/// conveniently define API functions and methods, use the facilities provided in engineAPI.h. 302/// 303/// @see engineAPI.h 304#define DEFINE_CALLIN( bindingName, exportName, scope, returnType, args, defaultArgs, flags, doc ) \ 305 TORQUE_API returnType bindingName args; \ 306 namespace { namespace _ ## bindingName { \ 307 _EngineFunctionDefaultArguments< void args > sDefaultArgs defaultArgs; \ 308 EngineFunctionInfo sFunctionInfo( \ 309 #exportName, \ 310 &_SCOPE< scope >()(), \ 311 doc, \ 312 #returnType " " #exportName #args, \ 313 #bindingName, \ 314 TYPE< returnType args >(), \ 315 &sDefaultArgs, \ 316 ( void* ) &bindingName, \ 317 _EngineFunctionFlags( flags ) \ 318 ); \ 319 } } \ 320 TORQUE_API returnType bindingName args 321 322 323/// 324/// 325/// Not all control layers may be able to access data variables in a DLL so this macro exposes 326/// both the variable and a set_XXX function to set the variable programmatically. 327#define DEFINE_CALLOUT( bindingName, exportName, scope, returnType, args, flags, doc ) \ 328 TORQUE_API returnType ( *bindingName ) args; \ 329 TORQUE_API void set_ ## bindingName( returnType ( *fn ) args ) \ 330 { bindingName = fn; } \ 331 returnType ( *bindingName ) args; \ 332 namespace { \ 333 ::EngineFunctionInfo _cb ## bindingName( \ 334 #exportName, \ 335 &::_SCOPE< scope >()(), \ 336 doc, \ 337 #returnType " " #exportName #args, \ 338 #bindingName, \ 339 ::TYPE< returnType args >(), \ 340 NULL, \ 341 ( void* ) &bindingName, \ 342 EngineFunctionCallout | EngineFunctionFlags( flags ) \ 343 ); \ 344 } 345 346 347#endif // !_ENGINEFUNCTIONS_H_ 348
