Skip to content

Commit 2b29bc6

Browse files
supporting cppyy
1 parent 5076c46 commit 2b29bc6

File tree

5 files changed

+162
-2
lines changed

5 files changed

+162
-2
lines changed

CMakeLists.txt

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ set(XEUS_CPP_SRC
213213
src/xoptions.cpp
214214
src/xparser.cpp
215215
src/xutils.cpp
216+
217+
# magics
218+
src/xmagics/pythonexec.cpp
216219
)
217220

218221
if(NOT EMSCRIPTEN)
@@ -377,6 +380,31 @@ macro(xeus_cpp_create_target target_name linkage output_name)
377380
target_link_libraries(${target_name} PRIVATE ${CMAKE_THREAD_LIBS_INIT})
378381
endif()
379382

383+
# Python Stuff
384+
if(NOT EMSCRIPTEN)
385+
find_package(Python COMPONENTS Interpreter Development)
386+
387+
target_include_directories(${target_name} PRIVATE ${Python_INCLUDE_DIRS})
388+
target_link_libraries(${target_name} PUBLIC ${Python_LIBRARIES})
389+
target_compile_options(${target_name} PRIVATE ${Python_CFLAGS_OTHER})
390+
else()
391+
set(Python_INCLUDE_DIRS
392+
"${CMAKE_PREFIX_PATH}/include/python3.11")
393+
set(Python_LIBRARIES
394+
"python3.11"
395+
"m"
396+
"bz2"
397+
"libz.a"
398+
"sqlite3"
399+
"ffi"
400+
)
401+
set(Python_CFLAGS_OTHER "-sUSE_ZLIB=1" "-sUSE_BZIP2=1")
402+
403+
target_include_directories(${target_name} PRIVATE ${Python_INCLUDE_DIRS})
404+
target_link_libraries(${target_name} PUBLIC ${Python_LIBRARIES})
405+
target_compile_options(${target_name} PRIVATE ${Python_CFLAGS_OTHER})
406+
endif()
407+
380408
endmacro()
381409

382410
# xeus-cpp-headers
@@ -437,18 +465,28 @@ endif()
437465
if(EMSCRIPTEN)
438466
include(WasmBuildOptions)
439467
find_package(xeus-lite REQUIRED)
468+
link_directories(BEFORE "${CMAKE_INSTALL_PREFIX}/lib")
440469
add_executable(xcpp src/main_emscripten_kernel.cpp )
441470
target_link_libraries(xcpp PRIVATE xeus-lite)
442471
xeus_cpp_set_kernel_options(xcpp)
443472
xeus_wasm_compile_options(xcpp)
444473
xeus_wasm_link_options(xcpp "web,worker")
445474
# TODO: Remove the exported runtime methods
446475
# after the next xeus release.
476+
# , \"ffi_call\", \"ffi_closure_alloc\", \"ffi_prep_cif\", \"ffi_prep_cif_var\", \"ffi_prep_closure_loc\", \"ffi_type_double\", \"ffi_type_float\", \"ffi_type_longdouble\", \"ffi_type_pointer\", \"ffi_type_sint16\", \"ffi_type_sint32\", \"ffi_type_sint64\", \"ffi_type_sint8\", \"ffi_type_uint16\", \"ffi_type_uint32\", \"ffi_type_uint64\", \"ffi_type_uint8\", \"ffi_type_void\"
447477
target_link_options(xcpp
448478
PUBLIC "SHELL: -s EXPORTED_RUNTIME_METHODS='[\"FS\",\"PATH\",\"LDSO\",\"loadDynamicLibrary\",\"ERRNO_CODES\"]'"
449479
PUBLIC "SHELL: --preload-file ${SYSROOT_PATH}/include@/include"
480+
PUBLIC "SHELL: --preload-file ${CPyCppyy_DIR}/include/CPyCppyy@/include/CPyCppyy"
481+
PUBLIC "SHELL: --preload-file ${CPyCppyy_BUILD_DIR}/libcppyy.so@/lib/python3.11/site-packages/libcppyy.so"
482+
PUBLIC "SHELL: --preload-file ${Cppyy_Backend_DIR}/python/cppyy_backend@/lib/python3.11/site-packages/cppyy_backend"
483+
PUBLIC "SHELL: --preload-file ${Cppyy_DIR}/python/cppyy@/lib/python3.11/site-packages/cppyy"
484+
PUBLIC "SHELL: --preload-file ${Cppyy_DIR}/python/cppyy_compat@/lib/python3.11/site-packages/cppyy_compat"
485+
PUBLIC "SHELL: --preload-file ${CMAKE_PREFIX_PATH}/lib/python3.11@/lib/python3.11"
486+
PUBLIC "SHELL: --preload-file ${CMAKE_PREFIX_PATH}/include/clang@/include/clang"
487+
PUBLIC "SHELL: --preload-file ${CMAKE_PREFIX_PATH}/include/clang-c@/include/clang-c"
450488
PUBLIC "SHELL: --post-js ${CMAKE_CURRENT_SOURCE_DIR}/wasm_patches/post.js"
451-
)
489+
)
452490
# TODO: Emscripten supports preloading files just once before it generates
453491
# the xcpp.data file (containing the binary representation of the file(s) we
454492
# want to include in our application).

environment-wasm-host.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,8 @@ dependencies:
99
- CppInterOp>=1.5.0
1010
- cpp-argparse
1111
- pugixml
12+
- python=3.11
13+
- bzip2
14+
- zlib
15+
- libffi
16+
- sqlite

src/xinterpreter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "xmagics/os.hpp"
2222
#include "xmagics/xassist.hpp"
2323
#endif
24+
#include "xmagics/pythonexec.hpp"
2425
#include "xparser.hpp"
2526
#include "xsystem.hpp"
2627

@@ -371,7 +372,7 @@ __get_cxx_version ()
371372
// executable(m_interpreter));
372373
// preamble_manager["magics"].get_cast<xmagics_manager>().register_magic("timeit",
373374
// timeit(&m_interpreter));
374-
// preamble_manager["magics"].get_cast<xmagics_manager>().register_magic("python", pythonexec());
375+
preamble_manager["magics"].get_cast<xmagics_manager>().register_magic("python", pythonexec());
375376
#ifndef EMSCRIPTEN
376377
preamble_manager["magics"].get_cast<xmagics_manager>().register_magic("xassist", xassist());
377378
preamble_manager["magics"].get_cast<xmagics_manager>().register_magic("file", writefile());

src/xmagics/pythonexec.cpp

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/************************************************************************************
2+
* Copyright (c) 2025, xeus-cpp contributors *
3+
* *
4+
* Distributed under the terms of the BSD 3-Clause License. *
5+
* *
6+
* The full license is in the file LICENSE, distributed with this software. *
7+
************************************************************************************/
8+
9+
#include "pythonexec.hpp"
10+
#include "../xparser.hpp"
11+
#include <string>
12+
13+
#include "Python.h"
14+
15+
#include "clang/Interpreter/CppInterOp.h"
16+
17+
namespace xcpp {
18+
bool pythonexec::is_initalized = false;
19+
20+
void pythonexec::operator()([[maybe_unused]] const std::string& line, const std::string& cell) {
21+
22+
if (!is_initalized)
23+
initialize();
24+
if (!is_initalized) {
25+
// initializing failed
26+
std::cout << Cpp::EndStdStreamCapture();
27+
std::cerr << Cpp::EndStdStreamCapture();
28+
29+
std::cerr << "Failed to Initialize Python\n";
30+
return;
31+
}
32+
33+
std::string code = trim(cell);
34+
if (code.empty())
35+
return;
36+
37+
Cpp::BeginStdStreamCapture(Cpp::kStdErr);
38+
Cpp::BeginStdStreamCapture(Cpp::kStdOut);
39+
40+
PyRun_SimpleString(code.c_str());
41+
42+
std::cout << Cpp::EndStdStreamCapture();
43+
std::cerr << Cpp::EndStdStreamCapture();
44+
}
45+
46+
void pythonexec::initialize() {
47+
#ifdef EMSCRIPTEN
48+
PyStatus status;
49+
50+
PyConfig config;
51+
PyConfig_InitPythonConfig(&config);
52+
static const std::wstring prefix(L"/");
53+
config.base_prefix = const_cast<wchar_t*>(prefix.c_str());
54+
config.base_exec_prefix = const_cast<wchar_t*>(prefix.c_str());
55+
config.prefix = const_cast<wchar_t*>(prefix.c_str());
56+
config.exec_prefix = const_cast<wchar_t*>(prefix.c_str());
57+
58+
status = Py_InitializeFromConfig(&config);
59+
if (PyStatus_Exception(status)) {
60+
// TODO: initialization failed, propagate error
61+
PyConfig_Clear(&config);
62+
is_initalized = false;
63+
return;
64+
}
65+
PyConfig_Clear(&config);
66+
#else
67+
Py_Initialize();
68+
#endif
69+
70+
PyRun_SimpleString("import sys\nsys.path.append('')"); // add current directory to PYTHONPATH
71+
72+
// // Import cppyy module
73+
// PyObject* cppyyModule = PyImport_ImportModule("cppyy");
74+
// if (!cppyyModule) {
75+
// PyErr_Print();
76+
// Py_Finalize();
77+
// return; // Handle import error as needed
78+
// }
79+
80+
// PyObject* mainModule = PyImport_AddModule("__main__");
81+
// PyObject_SetAttrString(mainModule, "cppyy", cppyyModule);
82+
// Py_XDECREF(cppyyModule);
83+
84+
is_initalized = true;
85+
}
86+
} // namespace xcpp

src/xmagics/pythonexec.hpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/************************************************************************************
2+
* Copyright (c) 2025, xeus-cpp contributors *
3+
* *
4+
* Distributed under the terms of the BSD 3-Clause License. *
5+
* *
6+
* The full license is in the file LICENSE, distributed with this software. *
7+
************************************************************************************/
8+
9+
#ifndef XEUS_CPP_PYTHONEXEC_MAGIC_HPP
10+
#define XEUS_CPP_PYTHONEXEC_MAGIC_HPP
11+
12+
#include <string>
13+
14+
#include "xeus-cpp/xmagics.hpp"
15+
16+
namespace xcpp
17+
{
18+
class pythonexec : public xmagic_cell
19+
{
20+
public:
21+
XEUS_CPP_API
22+
void operator()(const std::string& line, const std::string& cell) override;
23+
private:
24+
static bool is_initalized;
25+
void initialize();
26+
27+
};
28+
} // namespace xcpp
29+
30+
#endif //XEUS_CPP_PYTHONEXEC_MAGIC_HPP

0 commit comments

Comments
 (0)