Skip to main content
Glama
embedded_main.cpp4.9 kB
/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under both the MIT license found in the * LICENSE-MIT file in the root directory of this source tree and the Apache * License, Version 2.0 found in the LICENSE-APACHE file in the root directory * of this source tree. */ #include <Python.h> #include <stdlib.h> #include <sys/time.h> #include <functional> #include <optional> #include <string> namespace { // Scopeguard helper. class ScopeGuard { public: ScopeGuard(std::function<void(void)>&& func) : func(std::move(func)) {} ScopeGuard& operator=(ScopeGuard&& other) = default; ~ScopeGuard() { if (func) func(); } template <typename Func> static ScopeGuard create(Func&& func) { return ScopeGuard(std::move(func)); } private: std::function<void(void)> func; }; std::optional<int> MaybeGetExitCode(PyStatus* status, PyConfig* config) { if (PyStatus_IsExit(*status)) { return status->exitcode; } PyConfig_Clear(config); Py_ExitStatusException(*status); return std::nullopt; } } // namespace extern struct _inittab _static_extension_info[]; PyMODINIT_FUNC PyInit__static_extension_utils(); int main(int argc, char* argv[]) { PyStatus status; PyConfig config; PyConfig_InitPythonConfig(&config); status = PyConfig_SetBytesString(&config, &config.program_name, argv[0]); if (PyStatus_Exception(status)) { if (auto exit_code = MaybeGetExitCode(&status, &config)) { return *exit_code; } } #if PY_VERSION_HEX >= 0x030a0000 // 3.10 status = PyConfig_SetBytesArgv(&config, argc, argv); #else // Read all configuration at once. status = PyConfig_Read(&config); #endif if (PyStatus_Exception(status)) { if (auto exit_code = MaybeGetExitCode(&status, &config)) { return *exit_code; } } #if PY_VERSION_HEX >= 0x030a0000 // 3.10 // Read all configuration at once. status = PyConfig_Read(&config); #else status = PyConfig_SetBytesArgv(&config, argc, argv); #endif if (PyStatus_Exception(status)) { if (auto exit_code = MaybeGetExitCode(&status, &config)) { return *exit_code; } } // Check if we're using par_style="native", if so, modify sys.path to include // the executable-zipfile to it, and set a main module to run when invoked. #ifdef NATIVE_PAR_STYLE // Append path to the executable itself to sys.path. status = PyWideStringList_Append(&config.module_search_paths, config.executable); if (PyStatus_Exception(status)) { if (auto exit_code = MaybeGetExitCode(&status, &config)) { return *exit_code; } } // Run entry-point module at startup. status = PyConfig_SetBytesString(&config, &config.run_module, "__run_npar_main__"); if (PyStatus_Exception(status)) { if (auto exit_code = MaybeGetExitCode(&status, &config)) { return *exit_code; } } #endif /* NATIVE_PAR_STYLE */ // TODO (T129253406) We can do some code generation on build, we will have tho // full library name and the symbol name. FYI the currently we mangle symbol // names to avoid collision so PyInit_bye -> // PyInit_python_efficiency_experimental_linking_tests_bye // One issue with this is how we would resolve foo_bar.baz and foo.bar_baz in // both cases the name would be mangled to PyInit_foo_bar_baz... if (auto exit_code = PyImport_AppendInittab( "_static_extension_utils", PyInit__static_extension_utils); exit_code != 0) { PyErr_Print(); fprintf(stderr, "Error: could not update inittab\n"); return exit_code; } if (std::getenv("NP_DEBUG_BINARY")) { fprintf( stderr, "Pausing for debugger, pid=%d. Press <return> to continue.\n", (int)getpid()); fflush(stderr); getchar(); } status = Py_InitializeFromConfig(&config); if (PyStatus_Exception(status)) { if (auto exit_code = MaybeGetExitCode(&status, &config)) { return *exit_code; } } { auto sysPathGuard = ScopeGuard::create([=]() {}); // For fastzip, the `static_extensions_finder` module is found in the PAR, // and we're too early in the process to have the fastzip PAR auto-added to // the path (I think this happens in `Py_RunMain` below), so we need to get // it added for this block. const auto par = std::getenv("FB_PAR_FILENAME"); if (par != nullptr) { PyObject* sysPath = PySys_GetObject((char*)"path"); auto result = PyList_Insert(sysPath, 0, PyUnicode_FromString((char*)par)); if (result == -1) { PyErr_Print(); abort(); } sysPathGuard = ScopeGuard::create([=]() { auto result = PyObject_CallMethod(sysPath, "pop", "O", PyLong_FromLong(0)); if (result == nullptr) { PyErr_Print(); abort(); } Py_DECREF(result); }); }; } PyConfig_Clear(&config); return Py_RunMain(); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server