Skip to content
Snippets Groups Projects
Forked from waLBerla / waLBerla
65 commits behind the upstream repository.
PythonCallback.cpp 5.58 KiB
//======================================================================================================================
//
//  This file is part of waLBerla. waLBerla is free software: you can
//  redistribute it and/or modify it under the terms of the GNU General Public
//  License as published by the Free Software Foundation, either version 3 of
//  the License, or (at your option) any later version.
//
//  waLBerla is distributed in the hope that it will be useful, but WITHOUT
//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
//  for more details.
//
//  You should have received a copy of the GNU General Public License along
//  with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
//
//! \file PythonCallback.cpp
//! \ingroup python_coupling
//! \author Martin Bauer <martin.bauer@fau.de>
//! \author Markus Holzer <markus.holzer@fau.de>
//
//======================================================================================================================

#include "PythonCallback.h"
#include "DictWrapper.h"
#include "core/logging/all.h"
#ifdef WALBERLA_BUILD_WITH_PYTHON

#include "Manager.h"
#include "core/Abort.h"
#include "core/Filesystem.h"

#include "pybind11/eval.h"

namespace walberla {
namespace python_coupling {

   static py::object importModuleOrFileInternal( const std::string & fileOrModuleName, const std::vector< std::string > & argv )
   {
      auto manager = python_coupling::Manager::instance();
      manager->triggerInitialization();

      namespace py = pybind11;

      std::string moduleName = fileOrModuleName;

      std::stringstream code;
      code << "import sys" << "\n" ;
      code << "sys.argv = [ ";
      for( auto argStrIt = argv.begin(); argStrIt != argv.end(); ++argStrIt )
         code << "'" << *argStrIt  << "',";
      code << "] \n";

      filesystem::path path ( fileOrModuleName );
      path = filesystem::absolute( path );

      if ( path.extension() == ".py" )
      {
         moduleName = path.stem().string();
         if ( ! path.parent_path().empty() ) {
            std::string p = filesystem::canonical(path.parent_path()).string();
            code << "sys.path.append( r'" << p << "')" << "\n";
         }
      }

      py::exec( code.str().c_str(), py::module::import("__main__").attr("__dict__") );

      try {
         return py::module::import( moduleName.c_str() );
      }
      catch ( py::error_already_set &e) {