Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

392 lines
13 KiB

  1. //======= Copyright � 1996-2007, Valve Corporation, All rights reserved. ======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #ifndef VALVEPYTHON_H
  7. #define VALVEPYTHON_H
  8. #if defined( _WIN32 )
  9. #pragma once
  10. #endif
  11. // Python includes
  12. #include <Python.h>
  13. // Valve includes
  14. #include "interface.h"
  15. #include "tier1/utlvector.h"
  16. #include "tier1/utlstring.h"
  17. //-----------------------------------------------------------------------------
  18. // Call instead of Py_Initialize(), it will call Py_Initialize() after doing
  19. // a sanity check and possible repair of the PYTHONHOME environment variable
  20. //-----------------------------------------------------------------------------
  21. void Valve_Py_Initialize();
  22. //-----------------------------------------------------------------------------
  23. // Sets things up so python will print to Valve's "Spew" system
  24. //-----------------------------------------------------------------------------
  25. void PythonToSpew();
  26. //-----------------------------------------------------------------------------
  27. // Finds the GetAppFactory function in the specified python module and returns
  28. // the app factory handle or NULL on error
  29. //-----------------------------------------------------------------------------
  30. CreateInterfaceFn ValvePythonAppFactory( const char *pGetAppFactory = "GetAppFactory" );
  31. //=============================================================================
  32. //
  33. // Should be called by each module's init function
  34. //
  35. //=============================================================================
  36. bool ValvePythonInit( CreateInterfaceFn pInFactory = NULL );
  37. //=============================================================================
  38. //
  39. // Without DataModel
  40. //
  41. //=============================================================================
  42. bool ValvePythonInitNoDataModel( CreateInterfaceFn pInFactory = NULL );
  43. //=============================================================================
  44. //
  45. // Python command factory class
  46. //
  47. //=============================================================================
  48. class CValvePythonCommand
  49. {
  50. public:
  51. // Constructor
  52. CValvePythonCommand( const char *pName, PyCFunction pMeth, int nFlags, const char *pDoc )
  53. : m_name( pName )
  54. , m_pMeth( pMeth )
  55. , m_nFlags( nFlags )
  56. , m_doc( pDoc )
  57. {
  58. m_pNextFactory = s_pFirstFactory;
  59. s_pFirstFactory = this;
  60. }
  61. static void Register( char *pModuleName );
  62. protected:
  63. void Register( CUtlVector< PyMethodDef > &pyMethodDefs );
  64. private:
  65. // The next factory
  66. CValvePythonCommand *m_pNextFactory;
  67. static CValvePythonCommand *s_pFirstFactory;
  68. // Has to stay in same place in memory for duration of python
  69. static CUtlVector< PyMethodDef > s_pyMethodDefs;
  70. CUtlString m_name;
  71. PyCFunction m_pMeth;
  72. const int m_nFlags;
  73. CUtlString m_doc;
  74. };
  75. //-----------------------------------------------------------------------------
  76. // Macro to install a valve python command
  77. //
  78. // Use it like this:
  79. //
  80. // PYTHON_COMMAND( foo, METH_VARARGS, "The documentation for foo" )
  81. //-----------------------------------------------------------------------------
  82. #define PYTHON_COMMAND( _name, _flags, _doc ) \
  83. extern "C" static PyObject *_name##_pythonFunc( PyObject *pSelf, PyObject *pArgs ); \
  84. static CValvePythonCommand _name##_command( #_name, _name##_pythonFunc, _flags, _doc ); \
  85. extern "C" static PyObject *_name##_pythonFunc( PyObject *pSelf, PyObject *pArgs )
  86. //-----------------------------------------------------------------------------
  87. // Macro to install a valve python command which uses keywords in the interface
  88. //
  89. // Use it like this:
  90. //
  91. // PYTHON_COMMAND( foo, METH_VARARGS, "The documentation for foo" )
  92. //-----------------------------------------------------------------------------
  93. #define PYTHON_COMMAND_KEYWORDS( _name, _flags, _doc ) \
  94. extern "C" static PyObject *_name##_pythonFunc( PyObject *pSelf, PyObject *pArgs, PyObject *pKeywords ); \
  95. static CValvePythonCommand _name##_command( #_name, reinterpret_cast< PyCFunction >( _name##_pythonFunc ), _flags, _doc ); \
  96. extern "C" static PyObject *_name##_pythonFunc( PyObject *pSelf, PyObject *pArgs, PyObject *pKeywords )
  97. //=============================================================================
  98. //
  99. // Python sub module factory class
  100. //
  101. //=============================================================================
  102. class CValvePythonSubModule
  103. {
  104. public:
  105. typedef void ( *PythonInitFunc_t )( void );
  106. CValvePythonSubModule( const char *pName, PythonInitFunc_t pInitFunc )
  107. : m_name( pName )
  108. , m_pInitFunc( pInitFunc )
  109. {
  110. m_pNextFactory = s_pFirstFactory;
  111. s_pFirstFactory = this;
  112. }
  113. // Only Registers _<mod>.pyd
  114. static void Register( PyObject *pPackage );
  115. // Registers both the _<mod>.pyd & <mod>.py
  116. static void FullRegister( PyObject *pPackage );
  117. private:
  118. CValvePythonSubModule *m_pNextFactory;
  119. static CValvePythonSubModule *s_pFirstFactory;
  120. CUtlString m_name;
  121. PythonInitFunc_t m_pInitFunc;
  122. };
  123. //-----------------------------------------------------------------------------
  124. // Macro to install a valve python command
  125. //
  126. // Use it like this:
  127. //
  128. // PYTHON_COMMAND( foo, METH_VARARGS, "The documentation for foo" )
  129. //-----------------------------------------------------------------------------
  130. #ifndef SWIGEXPORT
  131. # if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
  132. # if defined(STATIC_LINKED)
  133. # define SWIGEXPORT
  134. # else
  135. # define SWIGEXPORT __declspec(dllexport)
  136. # endif
  137. # else
  138. # if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)
  139. # define SWIGEXPORT __attribute__ ((visibility("default")))
  140. # else
  141. # define SWIGEXPORT
  142. # endif
  143. # endif
  144. #endif
  145. #define PYTHON_SUBMODULE( _name ) \
  146. extern "C" SWIGEXPORT void init_##_name( void ); \
  147. static CValvePythonSubModule _name##_submodule( #_name, init_##_name ); \
  148. CValvePythonSubModule *g_p##_name##LinkerHack = NULL;
  149. #define REFERENCE_PYTHON_SUBMODULE( _name, _suffix ) \
  150. extern CValvePythonSubModule *g_p##_name##LinkerHack; \
  151. CValvePythonSubModule *g_p##_name##_suffix##PullInModule = g_p##_name##LinkerHack;
  152. // Support for implemented extended python commands which can take multiple position arguments and specified keyword arguments
  153. //
  154. typedef enum _pytypes
  155. {
  156. PY_FIELD_VOID = 0, // No type or value
  157. PY_FIELD_BOOLEAN, // boolean, implemented as an int, I may use this as a hint for compression
  158. PY_FIELD_CHARACTER, // a byte
  159. PY_FIELD_UTLSTRING, // CUtlString
  160. PY_FIELD_SHORT, // 2 byte integer
  161. PY_FIELD_INTEGER, // Any integer or enum
  162. PY_FIELD_FLOAT, // Any floating point value
  163. PY_FIELD_VECTOR, // Any vector, QAngle, or AngularImpulse
  164. PY_FIELD_QUATERNION, // A quaternion
  165. PY_FIELD_VMATRIX, // a Vmatrix (output coords are NOT worldspace)
  166. PY_FIELD_MATRIX3X4, // matrix3x4_t
  167. PY_FIELD_OBJECT, // generic object pointer
  168. PY_FIELD_TYPECOUNT, // MUST BE LAST
  169. } pytype_t;
  170. #define _PY_PARAMETER(var_name,type,parameter_name,help) { type, #var_name, offsetof(classNameTypedef, var_name), -1, parameter_name, help, NULL, sizeof( ((classNameTypedef *)0)->var_name ) }
  171. #define _PY_ARGUMENT(var_name,type,argument_index,help) { type, #var_name, offsetof(classNameTypedef, var_name), argument_index, "", help, NULL, sizeof( ((classNameTypedef *)0)->var_name ) }
  172. #define DEFINE_PY_PARAMETER(var_name,type,parameter_name,help) _PY_PARAMETER(var_name, type, parameter_name, help )
  173. #define DEFINE_PY_ARGUMENT(var_name,type,argument_index,help) _PY_ARGUMENT(var_name, type, argument_index, help )
  174. struct pydatamap_t;
  175. struct pytypedescription_t;
  176. #define SIZE_OF_ARRAY(p) _ARRAYSIZE(p)
  177. #define DECLARE_PY_PARAMETER_DESC() \
  178. static pydatamap_t m_ParameterMap; \
  179. static pydatamap_t *GetBaseParameterMap(); \
  180. template <typename T> friend void ParameterMapAccess(T *, pydatamap_t **p); \
  181. template <typename T> friend pydatamap_t *ParameterMapInit(T *); \
  182. virtual pydatamap_t *GetParameterMap( void );
  183. #define BEGIN_PY_PARAMETERS( className ) \
  184. pydatamap_t className::m_ParameterMap = { 0, 0, #className, NULL }; \
  185. pydatamap_t *className::GetParameterMap( void ) { return &m_ParameterMap; } \
  186. pydatamap_t *className::GetBaseParameterMap() { pydatamap_t *pResult; ParameterMapAccess((BaseClass *)NULL, &pResult); return pResult; } \
  187. BEGIN_PY_PARAMETERS_GUTS( className )
  188. #define BEGIN_PY_PARAMETERS_NO_BASE( className ) \
  189. pydatamap_t className::m_ParameterMap = { 0, 0, #className, NULL }; \
  190. pydatamap_t *className::GetParameterMap( void ) { return &m_ParameterMap; } \
  191. pydatamap_t *className::GetBaseParameterMap() { return NULL; } \
  192. BEGIN_PY_PARAMETERS_GUTS( className )
  193. #define BEGIN_PY_PARAMETERS_GUTS( className ) \
  194. template <typename T> pydatamap_t *ParameterMapInit(T *); \
  195. template <> pydatamap_t *ParameterMapInit<className>( className * ); \
  196. namespace className##_ParameterMapInit \
  197. { \
  198. pydatamap_t *g_DataMapHolder = ParameterMapInit( (className *)NULL ); /* This can/will be used for some clean up duties later */ \
  199. } \
  200. \
  201. template <> pydatamap_t *ParameterMapInit<className>( className * ) \
  202. { \
  203. typedef className classNameTypedef; \
  204. static CParameterGeneratedNameHolder nameHolder(#className); \
  205. className::m_ParameterMap.baseMap = className::GetBaseParameterMap(); \
  206. static pytypedescription_t dataDesc[] = \
  207. { \
  208. { PY_FIELD_VOID,0,0,0,0,0,0 }, /* so you can define "empty" tables */
  209. #define END_PY_PARAMETERS() \
  210. }; \
  211. \
  212. if ( sizeof( dataDesc ) > sizeof( dataDesc[0] ) ) \
  213. { \
  214. classNameTypedef::m_ParameterMap.dataNumFields = SIZE_OF_ARRAY( dataDesc ) - 1; \
  215. classNameTypedef::m_ParameterMap.dataDesc = &dataDesc[1]; \
  216. } \
  217. else \
  218. { \
  219. classNameTypedef::m_ParameterMap.dataNumFields = 1; \
  220. classNameTypedef::m_ParameterMap.dataDesc = dataDesc; \
  221. } \
  222. return &classNameTypedef::m_ParameterMap; \
  223. }
  224. #define IMPLEMENT_NULL_PY_PARAMETERS( derivedClass ) \
  225. BEGIN_PY_PARAMETERS_GUTS( derivedClass ) \
  226. END_PY_PARAMETERS()
  227. struct pytypedescription_t
  228. {
  229. pytype_t type;
  230. const char *var_name;
  231. int offset;
  232. // index of the argument in the script file function call
  233. int argument_index;
  234. // the name of the parameter in script files
  235. const char *parameter_name;
  236. const char *help;
  237. // For embedding additional datatables inside this one
  238. pydatamap_t *td; // NOT HOOKED UP YET!!!
  239. // Stores the actual member variable size in bytes
  240. int fieldSizeInBytes;
  241. };
  242. struct pydatamap_t
  243. {
  244. pytypedescription_t *dataDesc;
  245. int dataNumFields;
  246. char const *dataClassName;
  247. pydatamap_t *baseMap;
  248. };
  249. template <typename T>
  250. inline void ParameterMapAccess(T *ignored, pydatamap_t **p)
  251. {
  252. *p = &T::m_ParameterMap;
  253. }
  254. //-----------------------------------------------------------------------------
  255. class CParameterGeneratedNameHolder
  256. {
  257. public:
  258. CParameterGeneratedNameHolder( const char *pszBase )
  259. : m_pszBase(pszBase)
  260. {
  261. m_nLenBase = strlen( m_pszBase );
  262. }
  263. ~CParameterGeneratedNameHolder()
  264. {
  265. for ( int i = 0; i < m_Names.Count(); i++ )
  266. {
  267. delete m_Names[i];
  268. }
  269. }
  270. const char *GenerateName( const char *pszIdentifier )
  271. {
  272. char *pBuf = new char[m_nLenBase + strlen(pszIdentifier) + 1];
  273. strcpy( pBuf, m_pszBase );
  274. strcat( pBuf, pszIdentifier );
  275. m_Names.AddToTail( pBuf );
  276. return pBuf;
  277. }
  278. private:
  279. const char *m_pszBase;
  280. size_t m_nLenBase;
  281. CUtlVector<char *> m_Names;
  282. };
  283. #define PYTHON_COMMAND_EXTENDED( _className ) \
  284. static _className g_##_className##Instance;\
  285. extern "C" static PyObject *g_##_className##Dispatch( PyObject *pSelf, PyObject *pArgs, PyObject *pKeywords ) \
  286. { \
  287. return g_##_className##Instance.DispatchRaw( pSelf, pArgs, pKeywords ); \
  288. } \
  289. static CValvePythonCommand _className##_command( g_##_className##Instance.GetName(), reinterpret_cast< PyCFunction >( g_##_className##Dispatch ), g_##_className##Instance.GetFlags(), g_##_className##Instance.GetDoc() ); \
  290. class CBasePythonCommand
  291. {
  292. DECLARE_PY_PARAMETER_DESC();
  293. public:
  294. CBasePythonCommand( const char *pchCommandName, int nFlags, char const *pchHelpText, pydatamap_t *pDataMap );
  295. PyObject *DispatchRaw( PyObject *pSelf, PyObject *pArgs, PyObject *pKeywords );
  296. char const *GetName() const;
  297. char const *GetDoc() const;
  298. int GetFlags() const;
  299. virtual PyObject *Dispatch( CUtlVector< CUtlString > &args, CUtlVector< int > &typedArgs ) = 0;
  300. virtual void SetDefaults() = 0;
  301. private:
  302. void InitParameters();
  303. void ProcessArguments( PyObject *pArgs, PyObject *pKeywords, CUtlVector< CUtlString > &args, CUtlVector< int > &typedArgs );
  304. pytypedescription_t *FindParameter( char const *pchName );
  305. pytypedescription_t *FindArgument( int index );
  306. void ExtractParameter( char const *pchName, pytypedescription_t *pTypeDescription, PyObject *pValue );
  307. template <class T>
  308. inline bool IsParameterTypeValid( pytype_t, T * ) const;
  309. protected:
  310. CUtlString BuildAutoGeneratedField( char const *pchParameterName, char const *pchPrefix, int *pCounter );
  311. template < class T >
  312. inline bool GetParameter( char const *pchParameterName, T *value );
  313. protected:
  314. char const *m_pchCommandName;
  315. int m_nFlags;
  316. char const *m_pchBaseHelpText;
  317. CUtlString m_HelpText;
  318. pydatamap_t *m_pDataMap;
  319. };
  320. #endif // VALVEPYTHON_H