SST  14.1.0
StructuralSimulationToolkit
element_python.h
1 // Copyright 2009-2024 NTESS. Under the terms
2 // of Contract DE-NA0003525 with NTESS, the U.S.
3 // Government retains certain rights in this software.
4 //
5 // Copyright (c) 2009-2024, NTESS
6 // All rights reserved.
7 //
8 // This file is part of the SST software package. For license
9 // information, see the LICENSE file in the top level directory of the
10 // distribution.
11 
12 #ifndef SST_CORE_MODEL_ELEMENT_PYTHON_H
13 #define SST_CORE_MODEL_ELEMENT_PYTHON_H
14 
15 #include "sst/core/eli/elementinfo.h"
16 
17 #include <string>
18 #include <vector>
19 
20 namespace SST {
21 
22 typedef void* (*genPythonModuleFunction)(void);
23 
24 /** Class to represent the code that needs to be added to create the
25  * python module struture for the library.
26  */
28 {
29 
30 private:
31  //! Pointer to parent module.
32  /** Parent module. This will be nullptr if this is the primary module (i.e. sst.*) */
34 
35  //! Simple name of the module.
36  /** Simple name of the module. Full name will be parant_full_name.module_name */
37  std::string module_name;
38 
39  //! Code to be compiled
40  ///
41  /// The code to be added under the specified module name. Python
42  /// files will need to be turned into a char array. One way to do
43  /// this is to use the following in your Makefile:
44  /// %.inc: %.py
45  /// od -v -t x1 < $< | sed -e 's/^[^ ]*[ ]*//g' -e '/^\s*$$/d' -e 's/\([0-9a-f]*\)[ $$]*/0x\1,/g' > $@
46  ///
47  // (Used different comment style because command above would have ended a c-style comment block)
48  char* code;
49 
50  //! Filename used when reporting errors
51  /** Filename that will be used in any error messages generated
52  * when loading the python module into the interpreter.
53  */
54  std::string filename;
55 
56  //! Private constructor. Called by friend class SSTElementPythonModule.
57  /**
58  * Private constructor. Called by friend class SSTElementPythonModule.
59  * \param parent pointer to parent module
60  * \param module_name simple name of the module
61  * \param code code to be compiled
62  * \param filename filname used when reporting errors
63  * \sa parent, module_name, code, filename
64  */
66  SSTElementPythonModuleCode* parent, const std::string& module_name, char* code, std::string filename) :
67  parent(parent),
68  module_name(module_name),
69  code(code),
70  filename(filename)
71  {
72  // If no filename for debug is given, just set it to the full name of the module
73  if ( filename == "" ) { filename = getFullModuleName(); }
74  }
75 
76  //! load the code as a module into the interpreter
77  /**
78  * Load the code as a module into the interpreter.
79  * Both return type and pyobj are actually PyObject*, but passing
80  * as a void* to avoid including python header files in base SST
81  * header files.
82  * \param parent_module parent module (passed as PyObject*)to load this module under
83  * \return pointer (as PyObject*) to the created module
84  */
85  virtual void* load(void* parent_module);
86 
87  //! Vector of sub_modules
88  std::vector<SSTElementPythonModuleCode*> sub_modules;
89 
90  friend class SSTElementPythonModule;
91 
92 public:
93  //! Add a submodule to the module
94  ///
95  /// Python files will need to be turned into a char array (code parameter). One way to do
96  /// this is to use the following in your Makefile:
97  /// \verbatim %.inc: %.py
98  /// od -v -t x1 < $< | sed -e 's/^[^ ]*[ ]*//g' -e '/^\s*$$/d' -e 's/\([0-9a-f]*\)[ $$]*/0x\1,/g' > $@
99  /// \endverbatim
100  /// \param module_name simple name of the module
101  /// \param code code to be compiled
102  /// \param filename filname used when reporting errors
103  ///
104  ///
105  SSTElementPythonModuleCode* addSubModule(const std::string& module_name, char* code, const std::string& filename);
106 
107  //! Add an empty submodule to the module
108  ///
109  /// \param module_name simple name of the module
110  ///
111  ///
112  SSTElementPythonModuleCode* addSubModule(const std::string& module_name);
113 
114  //! Get the full name of the module
115  /**
116  * Get the full name of the module formatted as parent_full_name.module_name.
117  * \return full name of module as a string
118  */
119  std::string getFullModuleName();
120 };
121 
122 /**
123  Base class for python modules in element libraries.
124 
125  Element libraries can include a class derived from this class and
126  create a python module hierarchy.
127  */
129 {
130 
131 protected:
132  std::string library;
133  std::string pylibrary;
134  std::string sstlibrary;
135  char* primary_module;
136 
137  std::vector<std::pair<std::string, char*>> sub_modules;
138 
139  SSTElementPythonModuleCode* primary_code_module;
140 
141  // Only needed for supporting the old ELI
143 
144 public:
145  SST_ELI_DECLARE_BASE(SSTElementPythonModule)
146  SST_ELI_DECLARE_DEFAULT_INFO_EXTERN()
147  SST_ELI_DECLARE_CTOR_EXTERN(const std::string&)
148 
149  virtual ~SSTElementPythonModule() {}
150 
151  //! Constructor for SSTElementPythonModule. Must be called by derived class
152  /**
153  * \param library name of the element library the module is part
154  * of. Primary module name will be sst.library and submodules
155  * under this can also be created.
156  */
157  SSTElementPythonModule(const std::string& library);
158 
159  virtual void* load();
160 
161  //! Create the top level python module (i.e. the one named sst.library)
162  /// Python files will need to be turned into a char array (code parameter). One way to do
163  /// this is to use the following in your Makefile:
164  /// \verbatim %.inc: %.py
165  /// od -v -t x1 < $< | sed -e 's/^[^ ]*[ ]*//g' -e '/^\s*$$/d' -e 's/\([0-9a-f]*\)[ $$]*/0x\1,/g' > $@
166  /// \endverbatim
167  /// \param code code to be compiled
168  /// \param filename filname used when reporting errors
169  ///
170  ///
171  SSTElementPythonModuleCode* createPrimaryModule(char* code, const std::string& filename);
172 
173  //! Create and empty top level python module (i.e. the one named sst.library)
174  ///
175  ///
177 };
178 
179 } // namespace SST
180 
181 #define SST_ELI_REGISTER_PYTHON_MODULE(cls, lib, version) \
182  SST_ELI_REGISTER_DERIVED(SST::SSTElementPythonModule,cls,lib,lib,ELI_FORWARD_AS_ONE(version),"Python module " #cls)
183 
184 #endif // SST_CORE_MODEL_ELEMENT_PYTHON_H
std::string getFullModuleName()
Get the full name of the module.
Definition: element_python.cc:139
Definition: action.cc:18
SSTElementPythonModuleCode * createPrimaryModule()
Create and empty top level python module (i.e.
Definition: element_python.cc:212
SSTElementPythonModuleCode * addSubModule(const std::string &module_name, char *code, const std::string &filename)
Add a submodule to the module.
Definition: element_python.cc:94
Class to represent the code that needs to be added to create the python module struture for the libra...
Definition: element_python.h:27
Base class for python modules in element libraries.
Definition: element_python.h:128