BornAgain  1.18.0
Simulate and fit neutron and x-ray scattering at grazing incidence
PyImport Namespace Reference

Functions

std::unique_ptr< MultiLayercreateFromPython (const std::string &script, const std::string &functionName, const std::string &path="")
 
std::vector< std::string > listOfFunctions (const std::string &script, const std::string &path="")
 

Function Documentation

◆ createFromPython()

std::unique_ptr< MultiLayer > PyImport::createFromPython ( const std::string &  script,
const std::string &  functionName,
const std::string &  path = "" 
)

Creates a multi layer by running python code in embedded interpreter.

Parameters
scriptPython script
functionNameA function name in this script which produces a MultiLayer
pathA path to import BornAgain library. If empty, relies on PYTHONPATH

Definition at line 35 of file PyImport.cpp.

38 {
40 
41  PyObject* pCompiledFn = Py_CompileString(script.c_str(), "", Py_file_input);
42  if (!pCompiledFn)
43  throw std::runtime_error(error_description("Can't compile snippet"));
44 
45  // create a module
46  PyObject* pModule = PyImport_ExecCodeModule((char*)"test", pCompiledFn);
47  if (!pModule) {
48  Py_DecRef(pCompiledFn);
49  throw std::runtime_error(error_description("Can't exec module"));
50  }
51 
52  // locate the "get_simulation" function (it's an attribute of the module)
53  PyObject* pAddFn = PyObject_GetAttrString(pModule, functionName.c_str());
54  if (!pAddFn)
55  throw std::runtime_error("Can't locate compiled function");
56 
57  PyObject* instance = PyObject_CallFunctionObjArgs(pAddFn, NULL);
58  if (!instance) {
59  Py_DecRef(pAddFn);
60  Py_DecRef(pModule);
61  Py_DecRef(pCompiledFn);
62  throw std::runtime_error(error_description("Can't call function"));
63  }
64 
65  // clean up
66  Py_DecRef(pAddFn);
67  Py_DecRef(pModule);
68  Py_DecRef(pCompiledFn);
69 
70  void* argp1 = 0;
71  swig_type_info* pTypeInfo = SWIG_TypeQuery("MultiLayer *");
72 
73  const int res = SWIG_ConvertPtr(instance, &argp1, pTypeInfo, 0);
74  if (!SWIG_IsOK(res)) {
75  Py_DecRef(instance);
76  throw std::runtime_error("SWIG failed to extract a MultiLayer.");
77  }
78 
79  MultiLayer* multilayer = reinterpret_cast<MultiLayer*>(argp1);
80  std::unique_ptr<MultiLayer> result(multilayer->clone());
81 
82  Py_DecRef(instance);
83 
84  return result;
85 }
_object PyObject
Definition: PyObject.h:20
Our sample model: a stack of layers one below the other.
Definition: MultiLayer.h:42
MultiLayer * clone() const final override
Returns a clone of multilayer with clones of all layers and interfaces between layers.
Definition: MultiLayer.cpp:36
void import_bornagain(const std::string &path="")
Imports BornAgain from given location. If path is empty, tries to rely on PYTHONPATH.
std::string error_description(const std::string &title)
Definition: PyImport.cpp:25

References MultiLayer::clone(), anonymous_namespace{PyImport.cpp}::error_description(), and PyEmbeddedUtils::import_bornagain().

Here is the call graph for this function:

◆ listOfFunctions()

std::vector< std::string > PyImport::listOfFunctions ( const std::string &  script,
const std::string &  path = "" 
)

Returns list of functions defined in the script.

Parameters
scriptPython script
pathA path to import BornAgain library. If empty, relies on PYTHONPATH

Definition at line 87 of file PyImport.cpp.

89 {
91 
92  PyObject* pCompiledFn = Py_CompileString(script.c_str(), "", Py_file_input);
93  if (!pCompiledFn)
94  throw std::runtime_error(error_description("Can't compile snippet"));
95 
96  // create a module
97  PyObject* pModule = PyImport_ExecCodeModule((char*)"test", pCompiledFn);
98  if (!pModule) {
99  Py_DecRef(pCompiledFn);
100  throw std::runtime_error(error_description("Can't exec module"));
101  }
102 
103  PyObject* dict = PyModule_GetDict(pModule);
104  if (!dict)
105  throw std::runtime_error("Can't get dictionary from module");
106 
107  std::vector<std::string> result;
108  PyObject *key, *value;
109  Py_ssize_t pos = 0;
110  while (PyDict_Next(dict, &pos, &key, &value)) {
111  if (PyCallable_Check(value)) {
112  std::string func_name = PyEmbeddedUtils::toString(key);
113  if (func_name.find("__") == std::string::npos)
114  result.push_back(func_name);
115  }
116  }
117 
118  Py_DecRef(dict);
119  Py_DecRef(pModule);
120  Py_DecRef(pCompiledFn);
121 
122  return result;
123 }
std::string toString(PyObject *obj)
Converts PyObject into string, if possible, or throws exception.

References anonymous_namespace{PyImport.cpp}::error_description(), PyEmbeddedUtils::import_bornagain(), and PyEmbeddedUtils::toString().

Here is the call graph for this function: