12 #include <pybind11/embed.h>
18 #define STRINGIFY(x) #x
19 #define TOSTRING(x) STRINGIFY(x)
21 namespace fs = std::filesystem;
25 namespace pybind_wrappers {
30 #if defined(NMODL_STATIC_PYWRAPPER)
34 "nmodl_init_pybind_wrapper_api"));
37 if (init !=
nullptr) {
41 return init !=
nullptr;
49 std::string compiled_ver = fmt::format(
"{}.{}", PY_MAJOR_VERSION, PY_MINOR_VERSION);
50 auto pPy_GetVersion = (
const char* (*) (void) ) dlsym(RTLD_DEFAULT,
"Py_GetVersion");
51 if (pPy_GetVersion ==
nullptr) {
52 throw std::runtime_error(
"Unable to find the function `Py_GetVersion`");
54 const char* runtime_ver = pPy_GetVersion();
55 std::size_t len = compiled_ver.size();
56 if (std::strncmp(runtime_ver, compiled_ver.c_str(), len) != 0 ||
57 (runtime_ver[len] >=
'0' && runtime_ver[len] <=
'9')) {
58 throw std::runtime_error(
59 fmt::format(
"Python version mismatch. nmodl has been compiled with python {} and is "
60 "being run with python {}",
67 const auto pylib_env = std::getenv(
"NMODL_PYLIB");
69 logger->critical(
"NMODL_PYLIB environment variable must be set to load embedded python");
70 throw std::runtime_error(
"NMODL_PYLIB not set");
72 const auto dlopen_opts = RTLD_NOW | RTLD_GLOBAL;
76 const auto errstr = dlerror();
77 logger->critical(
"Tried but failed to load {}", pylib_env);
79 throw std::runtime_error(
"Failed to dlopen");
84 if (std::getenv(
"NMODLHOME") ==
nullptr) {
85 logger->critical(
"NMODLHOME environment variable must be set to load embedded python");
86 throw std::runtime_error(
"NMODLHOME not set");
88 auto pybind_wraplib_env = fs::path(std::getenv(
"NMODLHOME")) /
"lib" /
"libpywrapper";
90 if (!fs::exists(pybind_wraplib_env)) {
91 logger->critical(
"NMODLHOME doesn't contain libpywrapper{} library",
93 throw std::runtime_error(
"NMODLHOME doesn't have lib/libpywrapper library");
95 std::string env_str = pybind_wraplib_env.string();
98 const auto errstr = dlerror();
99 logger->critical(
"Tried but failed to load {}", pybind_wraplib_env.string());
101 throw std::runtime_error(
"Failed to dlopen");
106 #if defined(NMODL_STATIC_PYWRAPPER)
111 "nmodl_init_pybind_wrapper_api"));
115 const auto errstr = dlerror();
116 logger->critical(
"Tried but failed to load pybind wrapper symbols");
118 throw std::runtime_error(
"Failed to dlsym");