From d78818516670c1b15c275bee8e2804182c3c4883 Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Thu, 30 Jan 2025 10:16:55 +0530 Subject: [PATCH] supporting cppyy --- CMakeLists.txt | 37 ++++++++++++++++ environment-wasm-host.yml | 5 +++ src/xinterpreter.cpp | 3 +- src/xmagics/pythonexec.cpp | 86 ++++++++++++++++++++++++++++++++++++++ src/xmagics/pythonexec.hpp | 30 +++++++++++++ 5 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 src/xmagics/pythonexec.cpp create mode 100644 src/xmagics/pythonexec.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5273c3cb..313f3860 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -189,6 +189,9 @@ set(XEUS_CPP_SRC src/xparser.cpp src/xutils.cpp src/xmagics/os.cpp + + # magics + src/xmagics/pythonexec.cpp ) if(NOT EMSCRIPTEN) @@ -348,6 +351,31 @@ macro(xeus_cpp_create_target target_name linkage output_name) target_link_libraries(${target_name} PRIVATE ${CMAKE_THREAD_LIBS_INIT}) endif() + # Python Stuff + if(NOT EMSCRIPTEN) + find_package(Python COMPONENTS Interpreter Development) + + target_include_directories(${target_name} PRIVATE ${Python_INCLUDE_DIRS}) + target_link_libraries(${target_name} PUBLIC ${Python_LIBRARIES}) + target_compile_options(${target_name} PRIVATE ${Python_CFLAGS_OTHER}) + else() + set(Python_INCLUDE_DIRS + "${CMAKE_PREFIX_PATH}/include/python3.11") + set(Python_LIBRARIES + "python3.11" + "m" + "bz2" + "libz.a" + "sqlite3" + "ffi" + ) + set(Python_CFLAGS_OTHER "-sUSE_ZLIB=1" "-sUSE_BZIP2=1") + + target_include_directories(${target_name} PRIVATE ${Python_INCLUDE_DIRS}) + target_link_libraries(${target_name} PUBLIC ${Python_LIBRARIES}) + target_compile_options(${target_name} PRIVATE ${Python_CFLAGS_OTHER}) + endif() + endmacro() # xeus-cpp-headers @@ -416,6 +444,7 @@ if(EMSCRIPTEN) endif() include(WasmBuildOptions) find_package(xeus-lite ${xeus_lite_REQUIRED_VERSION} REQUIRED) + link_directories(BEFORE "${CMAKE_INSTALL_PREFIX}/lib") add_executable(xcpp src/main_emscripten_kernel.cpp ) target_link_libraries(xcpp PRIVATE xeus-lite) xeus_cpp_set_kernel_options(xcpp) @@ -429,6 +458,14 @@ if(EMSCRIPTEN) PUBLIC "SHELL: -s USE_SDL=2" PUBLIC "SHELL: --preload-file ${ESCAPED_SYSROOT_PATH}/include@/include" PUBLIC "SHELL: --preload-file ${ESCAPED_XEUS_CPP_RESOURCE_DIR}@/${CMAKE_INSTALL_LIBDIR}/clang/${CPPINTEROP_LLVM_VERSION_MAJOR}" + PUBLIC "SHELL: --preload-file ${CPyCppyy_DIR}/include/CPyCppyy@/include/CPyCppyy" + PUBLIC "SHELL: --preload-file ${CPyCppyy_BUILD_DIR}/libcppyy.so@/lib/python3.11/site-packages/libcppyy.so" + PUBLIC "SHELL: --preload-file ${Cppyy_Backend_DIR}/python/cppyy_backend@/lib/python3.11/site-packages/cppyy_backend" + PUBLIC "SHELL: --preload-file ${Cppyy_DIR}/python/cppyy@/lib/python3.11/site-packages/cppyy" + PUBLIC "SHELL: --preload-file ${Cppyy_DIR}/python/cppyy_compat@/lib/python3.11/site-packages/cppyy_compat" + PUBLIC "SHELL: --preload-file ${CMAKE_PREFIX_PATH}/lib/python3.11@/lib/python3.11" + PUBLIC "SHELL: --preload-file ${CMAKE_PREFIX_PATH}/include/clang@/include/clang" + PUBLIC "SHELL: --preload-file ${CMAKE_PREFIX_PATH}/include/clang-c@/include/clang-c" PUBLIC "SHELL: --post-js ${CMAKE_CURRENT_SOURCE_DIR}/wasm_patches/post.js" ) endif() diff --git a/environment-wasm-host.yml b/environment-wasm-host.yml index f0c24fee..8f830cba 100644 --- a/environment-wasm-host.yml +++ b/environment-wasm-host.yml @@ -10,3 +10,8 @@ dependencies: - cpp-argparse - pugixml - doctest + - python=3.12 + - bzip2 + - zlib + - libffi + - sqlite diff --git a/src/xinterpreter.cpp b/src/xinterpreter.cpp index 14972324..22b94c38 100644 --- a/src/xinterpreter.cpp +++ b/src/xinterpreter.cpp @@ -22,6 +22,7 @@ #ifndef EMSCRIPTEN #include "xmagics/xassist.hpp" #endif +#include "xmagics/pythonexec.hpp" #include "xparser.hpp" #include "xsystem.hpp" @@ -370,7 +371,7 @@ __get_cxx_version () // executable(m_interpreter)); // preamble_manager["magics"].get_cast().register_magic("timeit", // timeit(&m_interpreter)); - // preamble_manager["magics"].get_cast().register_magic("python", pythonexec()); + preamble_manager["magics"].get_cast().register_magic("python", pythonexec()); preamble_manager["magics"].get_cast().register_magic("file", writefile()); #ifndef EMSCRIPTEN preamble_manager["magics"].get_cast().register_magic("xassist", xassist()); diff --git a/src/xmagics/pythonexec.cpp b/src/xmagics/pythonexec.cpp new file mode 100644 index 00000000..895f6f02 --- /dev/null +++ b/src/xmagics/pythonexec.cpp @@ -0,0 +1,86 @@ +/************************************************************************************ + * Copyright (c) 2025, xeus-cpp contributors * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ************************************************************************************/ + +#include "pythonexec.hpp" +#include "../xparser.hpp" +#include + +#include "Python.h" + +#include "clang/Interpreter/CppInterOp.h" + +namespace xcpp { + bool pythonexec::is_initalized = false; + + void pythonexec::operator()([[maybe_unused]] const std::string& line, const std::string& cell) { + + if (!is_initalized) + initialize(); + if (!is_initalized) { + // initializing failed + std::cout << Cpp::EndStdStreamCapture(); + std::cerr << Cpp::EndStdStreamCapture(); + + std::cerr << "Failed to Initialize Python\n"; + return; + } + + std::string code = trim(cell); + if (code.empty()) + return; + + Cpp::BeginStdStreamCapture(Cpp::kStdErr); + Cpp::BeginStdStreamCapture(Cpp::kStdOut); + + PyRun_SimpleString(code.c_str()); + + std::cout << Cpp::EndStdStreamCapture(); + std::cerr << Cpp::EndStdStreamCapture(); + } + + void pythonexec::initialize() { +#ifdef EMSCRIPTEN + PyStatus status; + + PyConfig config; + PyConfig_InitPythonConfig(&config); + static const std::wstring prefix(L"/"); + config.base_prefix = const_cast(prefix.c_str()); + config.base_exec_prefix = const_cast(prefix.c_str()); + config.prefix = const_cast(prefix.c_str()); + config.exec_prefix = const_cast(prefix.c_str()); + + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + // TODO: initialization failed, propagate error + PyConfig_Clear(&config); + is_initalized = false; + return; + } + PyConfig_Clear(&config); +#else + Py_Initialize(); +#endif + + PyRun_SimpleString("import sys\nsys.path.append('')"); // add current directory to PYTHONPATH + + // // Import cppyy module + // PyObject* cppyyModule = PyImport_ImportModule("cppyy"); + // if (!cppyyModule) { + // PyErr_Print(); + // Py_Finalize(); + // return; // Handle import error as needed + // } + + // PyObject* mainModule = PyImport_AddModule("__main__"); + // PyObject_SetAttrString(mainModule, "cppyy", cppyyModule); + // Py_XDECREF(cppyyModule); + + is_initalized = true; + } +} // namespace xcpp diff --git a/src/xmagics/pythonexec.hpp b/src/xmagics/pythonexec.hpp new file mode 100644 index 00000000..3cbf1a18 --- /dev/null +++ b/src/xmagics/pythonexec.hpp @@ -0,0 +1,30 @@ +/************************************************************************************ + * Copyright (c) 2025, xeus-cpp contributors * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ************************************************************************************/ + +#ifndef XEUS_CPP_PYTHONEXEC_MAGIC_HPP +#define XEUS_CPP_PYTHONEXEC_MAGIC_HPP + +#include + +#include "xeus-cpp/xmagics.hpp" + +namespace xcpp +{ + class pythonexec : public xmagic_cell + { + public: + XEUS_CPP_API + void operator()(const std::string& line, const std::string& cell) override; + private: + static bool is_initalized; + void initialize(); + + }; +} // namespace xcpp + +#endif //XEUS_CPP_PYTHONEXEC_MAGIC_HPP