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