[英]Python C Extension: Linker says 'multiple definition of symbol'
I am currently working on creating a Python extension using C, which includes the definition of a custom object type.我目前正在使用 C 创建一个 Python 扩展,其中包括自定义 object 类型的定义。 In order to maintain a clear and organized codebase, I have chosen to define and implement this object in a separate file.
为了保持一个清晰和有组织的代码库,我选择在一个单独的文件中定义和实现这个 object。 However, as per the Python C API, functions and objects must be defined as static.
但是,根据 Python C API,函数和对象必须定义为 static。
Despite this, I have used the __attribute__((visibility("hidden")))
attribute for this object. Unfortunately, I am encountering a recurring error from the linker, specifically, "multiple definition of symbol."尽管如此,我还是为这个 object 使用了
__attribute__((visibility("hidden")))
属性。不幸的是,我遇到了来自 linker 的反复出现的错误,特别是“符号的多重定义”。
The code provided below is a minimal and easily replicable demonstration of the issue encountered in my larger project.下面提供的代码是我在大型项目中遇到的问题的最小且易于复制的演示。 Due to the large number of type objects present in the main project, I am seeking to organize them into separate files for improved maintainability.
由于主项目中存在大量类型对象,我正在寻求将它们组织到单独的文件中以提高可维护性。
.
├── example.c
├── include
│ ├── lcg.h
│ └── macros.h
├── lcg.c
└── setup.py
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "lcg.h"
static PyMethodDef example_methods[] = {
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef example_module = {
PyModuleDef_HEAD_INIT,
"example",
"An example module",
-1,
example_methods
};
PyMODINIT_FUNC PyInit_example(void) {
PyObject *module;
if (PyType_Ready(&LCG) < 0)
return NULL;
module = PyModule_Create(&example_module);
if (module == NULL)
return NULL;
Py_INCREF(&LCG);
PyModule_AddObject(module, "LCGType", (PyObject*)&LCG);
return module;
}
SYM_PRIVATE
is defined in macros.h
and expands to __attribute__((visibility("hidden")))
. SYM_PRIVATE
在macros.h
中定义并扩展为__attribute__((visibility("hidden")))
。
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "structmember.h"
#include "macros.h" /* for SYM_PRIVATE */
#include "lcg.h"
static PyObject *LCG__dummy(LCG_Type *self)
{
int value = 10;
return PyFloat_FromDouble(value);
}
static PyMemberDef LCG_members[] = {
{NULL} /* sentinel */
};
static PyMethodDef LCG_methods[] = {
{"dummy", (PyCFunction)LCG__dummy, METH_NOARGS, "A simple dummy function on LCG module."},
{NULL} /* sentinel */
};
SYM_PRIVATE PyTypeObject LCG = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "example.LCG",
.tp_doc = PyDoc_STR("Linear Congruential Generator"),
.tp_basicsize = sizeof(LCG_Type),
.tp_itemsize = 0,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_members = LCG_members,
.tp_methods = LCG_methods,
};
#ifndef LCG_H
#define LCG_H
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "structmember.h"
#include "macros.h" /* for SYM_PRIVATE */
typedef struct {
PyObject_HEAD
int foo;
} LCG_Type;
SYM_PRIVATE PyTypeObject LCG;
#endif /* LCG_H */
from setuptools import Extension
from setuptools import setup
example_module = Extension('example', sources=['example.c', 'lcg.c'], include_dirs=['include'])
setup(name = 'example',
version = '1.0',
description = 'An example module',
ext_modules = [example_module]
)
When executing python3.10 setup.py build
I got:执行
python3.10 setup.py build
时,我得到:
running build
running build_ext
building 'example' extension
creating build
creating build/temp.linux-x86_64-cpython-310
x86_64-linux-gnu-gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -fPIC -Iinclude -I/usr/include/python3.10 -c example.c -o build/temp.linux-x86_64-cpython-310/example.o
x86_64-linux-gnu-gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -fPIC -Iinclude -I/usr/include/python3.10 -c lcg.c -o build/temp.linux-x86_64-cpython-310/lcg.o
creating build/lib.linux-x86_64-cpython-310
x86_64-linux-gnu-gcc -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -g -fwrapv -O2 build/temp.linux-x86_64-cpython-310/example.o build/temp.linux-x86_64-cpython-310/lcg.o -L/usr/lib/x86_64-linux-gnu -o build/lib.linux-x86_64-cpython-310/example.cpython-310-x86_64-linux-gnu.so
/usr/bin/ld: build/temp.linux-x86_64-cpython-310/lcg.o:/home/user/workspaces/python-extension-example/src/include/lcg.h:14: multiple definition of `LCG'; build/temp.linux-x86_64-cpython-310/example.o:/home/user/workspaces/python-extension-example/src/include/lcg.h:14: first defined here
collect2: error: ld returned 1 exit status
error: command '/usr/bin/x86_64-linux-gnu-gcc' failed with exit code 1
I am running gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0
, GNU ld (GNU Binutils for Ubuntu) 2.38
and Python 3.10.6
.我正在运行
gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0
, GNU ld (GNU Binutils for Ubuntu) 2.38
和Python 3.10.6
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.