调试用C编写的Python扩展名

发布于 2025-01-21 04:53:49 字数 2241 浏览 3 评论 0 原文

我非常熟悉编写C代码,并且在编写Python代码方面很舒服。我正在尝试学习如何在C上从Python-3.9.x拨打的C中编写模块,OSX 10.15.7。我已经获得了一些“ Hello World”示例,但是对于复杂的示例,我努力弄清楚我将如何调试我编写的C延伸。

MWE:

src/add.c

// The C function that actually does the work
static PyObject * add_c_func(PyObject *self, PyObject *args)
{
    int a=0;
    int b=0;
    int c=0;

    // This determines the number arguments used by add_c_func
    if (!PyArg_ParseTuple(args, "iii", &a, &b, &c))
    {
        return NULL;
    }

    printf("%i\n", a+b+c);

    Py_RETURN_NONE;
}

// This defines the function used by
static PyMethodDef AddMethods[] = {
    {"add_py_func", add_c_func, METH_VARARGS, "Add three numbers."},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef addpymod =
{
    PyModuleDef_HEAD_INIT,
    "addpymod",     /* name of module */
    "",          /* module documentation, may be NULL */
    -1,          /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
    AddMethods
};

PyMODINIT_FUNC PyInit_addpymod(void)
{
    return PyModule_Create(&addpymod);
}

setup.py:

from setuptools import setup, Extension
setup(
    name='addpymod',
    version='1.0',
    description='Python Package with Hello World C Extension',
    ext_modules=[
        Extension(
            'addpymod',
            sources=['src/add.c'],
            py_limited_api=True)
    ],
)

编译/安装(默认情况下,它使用 clang ):

python setup.py install

尝试调试:

(py-ext-test) local: understand-python-c-ext $ gdb
GNU gdb (GDB) 10.1
.
.
.
(gdb) b add.c : 20
No symbol table is loaded.  Use the "file" command.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (add.c : 20) pending.
(gdb) python
>import addpymod
>addpymod.add_py_func(10,10,10)   # Why didn't my breakpoint get hit?
>Quit
# This clearly failed, I'm not even sure where my stdout is

有多个这里的复杂性水平,我敢肯定我会被多个。

问题

  1. 如何使用 add.c 使用 gdb (首选)或可能 lldb ,因为它已编译为默认情况下使用 clang 's -g 选项?

I'm pretty familiar with writing C code and I'm comfortable in writing python code. I'm trying to learn how to write modules in C that can be called from Python-3.9.X on OSX 10.15.7. I've gotten a couple 'hello world' type of examples to work, but for complex examples I'm struggling to figure out how I would debug the C-extensions that I write.

MWE:

src/add.c

// The C function that actually does the work
static PyObject * add_c_func(PyObject *self, PyObject *args)
{
    int a=0;
    int b=0;
    int c=0;

    // This determines the number arguments used by add_c_func
    if (!PyArg_ParseTuple(args, "iii", &a, &b, &c))
    {
        return NULL;
    }

    printf("%i\n", a+b+c);

    Py_RETURN_NONE;
}

// This defines the function used by
static PyMethodDef AddMethods[] = {
    {"add_py_func", add_c_func, METH_VARARGS, "Add three numbers."},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef addpymod =
{
    PyModuleDef_HEAD_INIT,
    "addpymod",     /* name of module */
    "",          /* module documentation, may be NULL */
    -1,          /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
    AddMethods
};

PyMODINIT_FUNC PyInit_addpymod(void)
{
    return PyModule_Create(&addpymod);
}

setup.py :

from setuptools import setup, Extension
setup(
    name='addpymod',
    version='1.0',
    description='Python Package with Hello World C Extension',
    ext_modules=[
        Extension(
            'addpymod',
            sources=['src/add.c'],
            py_limited_api=True)
    ],
)

Compiling / installing (by default it uses clang):

python setup.py install

Trying to debug :

(py-ext-test) local: understand-python-c-ext $ gdb
GNU gdb (GDB) 10.1
.
.
.
(gdb) b add.c : 20
No symbol table is loaded.  Use the "file" command.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (add.c : 20) pending.
(gdb) python
>import addpymod
>addpymod.add_py_func(10,10,10)   # Why didn't my breakpoint get hit?
>Quit
# This clearly failed, I'm not even sure where my stdout is

There are multiple levels of complexity here and I'm sure that I'm being tripped by more than one.

Question :

  1. How do I debug my add.c using gdb (preferred) or possibly lldb since it was compiled by default with clang's -g option?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

好听的两个字的网名 2025-01-28 04:53:49

使用 scikit-build-core 进行构建,但是关键是要使用调试构建构建。使用 Scikit -Build -core 可以使用:

[tool.scikit-build]
cmake.build-type = "Debug"

cmakelists.txt with:with with:

target_compile_options(my_ext PRIVATE -g -O0)

一旦您编译(例如 pip install -e。 -no-build-isolation ),仔细检查您的扩展名是否使用调试符号构建:

$objdump --syms /path/to/your/extension.so

您应该看到一张符号表。例如:

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c

然后,您将能够运行GDB并设置一个断点。例如:

$ gdb --args python test_ext.py
(gdb) b qual.cpp:4872
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (qual.cpp:4872) pending.
(gdb) run
Thread 1 "python" hit Breakpoint 1, ComputeWeights<float> (offset=0x1fe5830, neigh=0x20432e0, 
indices=0x1bb8ec0, points=0x1d6a7a0, n_neigh=108, n_points=27, fac=-0.75, num_threads=4) at /home/user/library-path/src/qual.cpp:4872                                          
4872      T *weights = new T[n_neigh];
(gdb) 

Ran into a similar issue on Linux using nanobind. I'm building using cmake and scikit-build-core, but the the key is to build using a debug build. Using scikit-build-core this can be set with:

[tool.scikit-build]
cmake.build-type = "Debug"

And within your CMakeLists.txt with:

target_compile_options(my_ext PRIVATE -g -O0)

Once you've compiled (e.g. pip install -e . --no-build-isolation), double check that your extension was built with debug symbols with:

$objdump --syms /path/to/your/extension.so

You should see a table of symbols. For example:

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c

You'll then be able to run gdb and set a breakpoint. For example:

$ gdb --args python test_ext.py
(gdb) b qual.cpp:4872
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (qual.cpp:4872) pending.
(gdb) run
Thread 1 "python" hit Breakpoint 1, ComputeWeights<float> (offset=0x1fe5830, neigh=0x20432e0, 
indices=0x1bb8ec0, points=0x1d6a7a0, n_neigh=108, n_points=27, fac=-0.75, num_threads=4) at /home/user/library-path/src/qual.cpp:4872                                          
4872      T *weights = new T[n_neigh];
(gdb) 
千年*琉璃梦 2025-01-28 04:53:49

@Alex Kaszynski是正确的,您缺少适当的编译标志来实现调试。由于您使用的是setUptools,因此您必须具体写作:

from setuptools import setup, Extension

compile_args = ["-g"]
setup(
    name='addpymod',
    version='1.0',
    description='Python Package with Hello World C Extension',
    ext_modules=[
        Extension(
            'addpymod',
            sources=['src/add.c'],
            py_limited_api=True,
            extra_compile_args=extra_compile_args,
        )
    ],
)

在这里我使用了-g,尽管您可以选择许多不同的调试标志如果您发现其他更适合

其价值的其他内容,我已经写了很多关于调试Python Extensions

@Alex Kaszynski is correct that you are missing the proper compilation flags to enable debugging. Since you are using setuptools, you would more specifically have to write:

from setuptools import setup, Extension

compile_args = ["-g"]
setup(
    name='addpymod',
    version='1.0',
    description='Python Package with Hello World C Extension',
    ext_modules=[
        Extension(
            'addpymod',
            sources=['src/add.c'],
            py_limited_api=True,
            extra_compile_args=extra_compile_args,
        )
    ],
)

Here I've used -g, though you may opt for many different debug flags if you find anything else more suitable

For what it's worth, I've written extensively about debugging Python extensions on my blog, so you may find more valuable information there

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文