question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Document how to embed Cython modules in C/C++ applications

See original GitHub issue

The documentation on embedding is inherently lacking. Even the one in the CPython docs is incomplete at best.

There are some hints in the Wiki, there’s the --embed option to the cython and cythonize frontends, the embedding demo, the PyImport_AppendInittab() function in CPython and the documentation of the module init function in CPython.

All of these are incomplete and none of them gives the whole picture in one place. There should be a dedicated documentation page in the Cython docs for this, and the documentation in the CPython docs is also worth improving.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:5
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
scodercommented, Jun 2, 2020

Please don’t use the bug tracker for general discussions. We have the cython-users mailing list for this.

0reactions
da-woodscommented, Nov 26, 2022

FWIW I have a working example of how to call PyInit_* on a multi-phase init module therefore avoiding the need to use PyImport_AppendInittab. Essentially it’s running through the multi-phase init steps manually. I’m not sure if we want to put it in any updated embedding docs, but it’s posted below in case anyone wants to document it properly:

I suspect this comes under

Most importantly, DO NOT call the module init function instead of importing the module. This is not the right way to initialise an extension module. (It was always wrong but used to work before, but since Python 3.5, it is wrong and no longer works.)

though

#include <Python.h>

#include "embed_example.h"

int main() {
    int result = 1;
    PyObject *spec = NULL, *spec_globals = NULL, *mod = NULL;
    Py_Initialize();
    PyObject *maybe_mod = PyInit_embed_example();
    if (!maybe_mod) goto bad;
    if (Py_IS_TYPE(maybe_mod, &PyModuleDef_Type)) {
        // multi-phase init
        spec_globals = PyDict_New();
        if (!spec_globals) goto bad;
        PyObject *res = PyRun_String(
            "import importlib.machinery as im\n"
            // Note that Cython doesn't actually use the loader
            // so it can be None. It'd be better to
            // provide something more useful though.
            "spec = im.ModuleSpec('embed_example', None)\n",
            Py_file_input, spec_globals, spec_globals);
        Py_XDECREF(res); // don't use res whether or not it's set
        if (!res) goto bad;
        spec = PyDict_GetItemString(spec_globals, "spec");
        if (!spec) goto bad;               
        
        mod = PyModule_FromDefAndSpec(
            (PyModuleDef*)maybe_mod,
            spec);
        if (!mod) goto bad;
        int execRes = PyModule_ExecDef(mod, (PyModuleDef*)maybe_mod);
        if (execRes) goto bad;
    } else {
        mod = maybe_mod;
    }
    
    func(); // cdef public in the module being embedded.
    
    result = 0;
    if (0) {
        bad:
        PyErr_Print();
    }
    // The moduledef isn't an owned reference so doesn't get decref'd
    Py_XDECREF(mod);
    Py_XDECREF(spec);
    Py_XDECREF(spec_globals);
    Py_Finalize();
    return result;    
}

I remain sceptical of whether embedding Cython in C/C++ applications is actually useful (because people expect it to embed their module and all its dependencies), but multi-phase init is definitely something that people fight with, and additional ways to work with it are probably good.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Embedding Cython modules in C/C++ applications
See the documentation of the module init function in CPython and PEP 489 ... the main steps for embedding a Cython module (...
Read more >
Add python modules to cython for use in c - Stack Overflow
When you read the documentation, you'd have seen that all the examples ("Using Cython declarations from C" and "Embedding Cython modules.
Read more >
[cython-users] embedding many cython modules in C++ project
So currently I've got a makefile that identifies all pyx/py files and runs cython on them to generate .cpp files. The compiler is...
Read more >
Extending and Embedding the Python Interpreter — Python ...
This document describes how to write modules in C or C++ to extend the Python interpreter with new modules. Those modules can not...
Read more >
Write C++ extensions for Python - Visual Studio (Windows)
To create a C++ file in the new project, right-click the Source Files node, and then select Add > New Item. Select C++...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found