Python C扩展多文件架构下PyTypeObject跨文件共享问题问询
Absolutely, using extern is the right approach here—this is a standard C pattern for sharing global symbols across compilation units, and it works perfectly for Python C extensions. Let's break down the exact steps to fix your setup:
Step 1: Adjust the PyTypeObject Definitions in my_module_main.c
First, you'll need to remove the static modifier from your PyTypeObject instances in my_module_main.c. The static keyword restricts the variable's scope to the current file, which is exactly why other .c files can't access them.
Example in my_module_main.c:
#include "my_module_defs.h" // Remove 'static' to make these global symbols accessible across files PyTypeObject MyModuleFoo_Type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "my_module.Foo", .tp_basicsize = sizeof(FooObject), .tp_itemsize = 0, .tp_flags = Py_TPFLAGS_DEFAULT, // ... rest of your type definition }; PyTypeObject MyModuleBar_Type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "my_module.Bar", .tp_basicsize = sizeof(BarObject), .tp_itemsize = 0, .tp_flags = Py_TPFLAGS_DEFAULT, // ... rest of your type definition };
Step 2: Add extern Declarations in my_module_defs.h
Next, declare these PyTypeObject instances in your shared header file using extern. This tells the compiler that the actual definition lives in another compilation unit (in this case, my_module_main.c).
Don't forget to add header guards to prevent duplicate declaration errors:
#ifndef MY_MODULE_DEFS_H #define MY_MODULE_DEFS_H #include <Python.h> // Forward-declare your type objects for cross-file access extern PyTypeObject MyModuleFoo_Type; extern PyTypeObject MyModuleBar_Type; // Include other shared definitions/function prototypes here // e.g., typedef struct { PyObject_HEAD; /* Foo fields */ } FooObject; #endif // MY_MODULE_DEFS_H
Step 3: Use the Type Objects in my_module_foo.c and my_module_bar.c
Now, in your implementation files, just include my_module_defs.h and you'll have full access to the PyTypeObject instances. For example, in my_module_foo.c:
#include "my_module_defs.h" static PyObject* foo_do_something(PyObject* self, PyObject* args) { // Verify the instance is of the correct type using the shared PyTypeObject if (!PyObject_TypeCheck(self, &MyModuleFoo_Type)) { PyErr_SetString(PyExc_TypeError, "Expected a my_module.Foo instance"); return NULL; } // ... your implementation logic here ... Py_RETURN_NONE; }
Key Notes
- Why this works: By removing
static, you turn thePyTypeObjectinto global symbols that the linker can resolve across files. Theexterndeclaration in the header lets other files know the symbol exists without redefining it. - Header guards are non-negotiable: They prevent the compiler from seeing multiple declarations of the same
PyTypeObjectwhen the header is included in multiple.cfiles. - Keep module initialization clean: Make sure your module definition in
my_module_main.cstill registers these types correctly, like so:static struct PyModuleDef my_module_module = { PyModuleDef_HEAD_INIT, .m_name = "my_module", .m_doc = "My Python C extension module", .m_size = -1, .m_classes = (PyTypeObject*[]) { &MyModuleFoo_Type, &MyModuleBar_Type, NULL }, // ... other module fields };
This approach is robust, follows C best practices, and is the standard way to share such objects in Python C extensions.
内容的提问来源于stack exchange,提问作者Charlie Sale

