NAP
pythonmodule.h
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4 
5 #pragma once
6 
7 #ifdef NAP_ENABLE_PYTHON
8 
9 #include <functional>
10 #include <vector>
11 #include <utility/dllexport.h>
12 
13 #include <pybind11/pybind11.h>
14 #include <pybind11/embed.h>
15 #include <pybind11/stl.h>
16 
17 // Note: including rttr headers directly here instead of going through typeinfo.h to avoid circular dependencies between the two headers
18 #include <rttr/detail/misc/misc_type_traits.h>
19 #include <rttr/type>
20 
21 namespace nap
22 {
23  namespace rtti
24  {
25  namespace detail
26  {
39  template<typename T>
40  inline void GetTypeNamesImpl(std::vector<std::string>& result)
41  {
42  result.push_back(rttr::type::get<T>().get_name().data());
43  }
44 
45  template<typename... Targs>
46  inline void GetTypeNames(std::vector<std::string>& result);
47 
48  template<typename T, typename... V>
49  inline void GetTypeNamesHelper(std::vector<std::string>& result)
50  {
51  GetTypeNamesImpl<T>(result);
52  GetTypeNames<V...>(result);
53  }
54 
55  template<typename... Targs>
56  inline void GetTypeNames(std::vector<std::string>& result)
57  {
58  GetTypeNamesHelper<Targs...>(result);
59  }
60 
61  template<>
62  inline void GetTypeNames<>(std::vector<std::string>& result)
63  {
64  }
65  }
66 
67  template<class T, class BaseClasses>
68  class PythonClass;
69 
101  template<class T, typename... BaseClasses>
102  class PythonClass<T, rttr::detail::type_list<BaseClasses...>>
103  {
104  public:
105  using PybindClass = pybind11::class_<T, BaseClasses...>;
106  using RegistrationFunction = std::function<void(pybind11::module&, PybindClass&)>;
107 
112  PythonClass(const std::string& name)
113  {
114  // Strip namespace out of type name
115  int namespace_separator_pos = name.find_last_of(':');
116  if (namespace_separator_pos != std::string::npos)
117  mName = name.substr(namespace_separator_pos+1);
118  else
119  mName = name;
120  }
121 
125  void registerFunction(const RegistrationFunction& function)
126  {
127  mRegistrationFunctions.push_back(function);
128  }
129 
133  void invoke(pybind11::module& module) const
134  {
135  auto cls = PybindClass(module, mName.c_str());
136  for (auto& func : mRegistrationFunctions)
137  func(module, cls);
138  }
139 
145  static void GetBaseTypes(std::vector<std::string>& baseClasses)
146  {
147  detail::GetTypeNames<BaseClasses...>(baseClasses);
148  }
149 
150  private:
151  std::string mName;
152  std::vector<std::string> mBaseTypes;
153  std::vector<RegistrationFunction> mRegistrationFunctions;
154  };
155 
177  class NAPAPI PythonModule
178  {
179  public:
180  using RegistrationFunction = std::function<void(pybind11::module&)>;
181  using GetBaseTypesFunction = std::function<void(std::vector<std::string>&)>;
182 
188  static PythonModule& get(const char* moduleName);
189 
193  void registerImportCallback(RegistrationFunction function);
194 
201  void registerTypeImportCallback(const std::string& name, GetBaseTypesFunction getBaseTypesFunction, RegistrationFunction registrationFunction);
202 
206  void invoke(pybind11::module& module);
207 
208  private:
212  struct RegistrationItem
213  {
214  GetBaseTypesFunction mGetBaseTypesFunction;
215  RegistrationFunction mRegistrationFunction;
216  };
217  using RegistrationMap = std::unordered_map<std::string, RegistrationItem>;
218 
224  void registerTypeRecursive(pybind11::module& module, RegistrationMap::iterator itemToRegister);
225 
226  RegistrationMap mRegistrationMap;
227  std::vector<RegistrationFunction> mImportCallbacks;
228  };
229  }
230 }
231 
232 #endif
nap
Definition: templateapp.h:17