Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions python/cppjit/_cpython_cppjit.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""CPython-specific touch-ups"""

import ctypes
import importlib.util

from . import _stdcpp_fix # noqa: F401

Expand All @@ -16,13 +17,17 @@
"_end_capture_stderr",
]

# the merged libcppjit extension is the backend: importing it loads the
# C++ runtime (no separate loader.load_cpp_backend() step, which would
# initialize the interpreter twice)
import libcppjit as _backend

# explicitly expose APIs from libcppjit
_w = ctypes.CDLL(_backend.__file__, ctypes.RTLD_GLOBAL)
# preload the merged extension with ctypes and run LoadCppInterOp() first,
# so the interpreter is ready before the extension module initializes
_spec = importlib.util.find_spec("libcppjit")
if _spec is None or not _spec.origin:
raise ImportError("cannot locate the libcppjit extension module")
_w = ctypes.CDLL(_spec.origin, ctypes.RTLD_GLOBAL)
if not _w.LoadCppInterOp():
raise RuntimeError("failed to load CppInterOp (LoadCppInterOp returned 0)")
del _spec

import libcppjit as _backend # noqa: E402


### template support ---------------------------------------------------------
Expand Down
33 changes: 20 additions & 13 deletions src/interop/interop_wrapper.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,20 @@ static InterOpPaths cppinterop_paths() {
(anchor / CPPINTEROP_INCLUDE_DIR).string()};
}

class ApplicationStarter {
interop::TInterp_t Interp;
} // unnamed namespace

public:
ApplicationStarter() {
// Load CppInterOp and set up the interpreter. A dlopen during static
// initialization is unsafe, so _cpython_cppjit.py calls this explicitly
// before the first libcppjit use. Thread-safe and idempotent; returns 1 on
// success.
extern "C" {
RPY_EXPORTED int LoadCppInterOp();
}

extern "C" int LoadCppInterOp() {
static std::once_flag Once;
static int Loaded = 0;
std::call_once(Once, [] {
std::lock_guard<std::recursive_mutex> Lock(InterOpMutex);
const InterOpPaths Paths = cppinterop_paths();
if (!Cpp::LoadDispatchAPI(Paths.Library.c_str())) {
Expand All @@ -111,17 +120,14 @@ class ApplicationStarter {
}
// Check if somebody already loaded CppInterOp and created an
// interpreter for us.
if (auto existingInterp = Cpp::GetInterpreter()) {
Interp = existingInterp;
} else {
if (!Cpp::GetInterpreter()) {
// CppInterOp itself appends CPPINTEROP_EXTRA_INTERPRETER_ARGS inside
// CreateInterpreter, so nothing needs to be forwarded from here.
#if defined(__arm64__) && defined(__APPLE__)
// If on apple silicon don't use -march=native
Interp = Cpp::CreateInterpreter({"-std=c++17"}, /*GpuArgs=*/{});
Cpp::CreateInterpreter({"-std=c++17"}, /*GpuArgs=*/{});
#else
Interp = Cpp::CreateInterpreter({"-std=c++17", "-march=native"},
/*GpuArgs=*/{});
Cpp::CreateInterpreter({"-std=c++17", "-march=native"}, /*GpuArgs=*/{});
#endif
}

Expand Down Expand Up @@ -191,10 +197,11 @@ class ApplicationStarter {
// helper for multiple inheritance
Cpp::Declare("namespace __cppjit_internal { struct Sep; }",
/*silent=*/false);
}
} _applicationStarter;

} // unnamed namespace
Loaded = 1;
});
return Loaded;
}

// local helpers -------------------------------------------------------------
static inline char* cppstring_to_cstring(const std::string& cppstr) {
Expand Down
Loading