Python导入错误:自定义C模块的未定义符号

huangapple go评论139阅读模式
英文:

Python Import Error: Undefined Symbol for Custom C Module

问题

I've translated the content as requested:

我一直在Python中尝试使用C模块,编译没有问题。但是,在导入模块时,我收到以下错误消息:

>>> import _strrev
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: /path/to/my/module.so: undefined symbol: strrev

文件的内容如下:

_strrev.c

#include <Python.h>
#include <string.h>
static PyObject* _strrev(PyObject* self, PyObject *args) {
   PyObject* name;
   if (!PyArg_ParseTuple(args, "U", &name)) {
       return NULL; 
   }
   PyObject *ret = strrev(*name); 

   return ret;
}

static struct PyMethodDef methods[] = {
    {"strrev", (PyCFunction)_strrev, METH_VARARGS},
    {NULL, NULL}
};

static struct PyModuleDef module = {
    PyModuleDef_HEAD_INIT, 
    "_strrev",
    NULL, 
    -1, 
    methods
};

PyMODINIT_FUNC PyInit__strrev(void) {
    return PyModule_Create(&module);
}

setup.py

from distutils.core import setup, Extension

setup(
        name='strrev_lib',
        version='1',
        ext_modules=[Extension('_strrev', ['_strrev.c'])],
        )

运行这个对象文件上的nm -D命令时,我得到以下输出:

$ nm -D _strrev.cpython-39-x86_64-linux-gnu.so 
                 w __cxa_finalize@GLIBC_2.2.5
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U PyArg_ParseTuple
00000000000011a0 T PyInit__strrev
                 U PyModule_Create2
                 U __stack_chk_fail@GLIBC_2.4
                 U strrev

我可以看到strrev在这里,所以我不明白为什么它说该符号未定义。

我还尝试使用不同的模块,当尝试导入它时,它完全正常运行。

$ python3
Python 3.9.2 (default, Feb 28 2021, 17:03:44) 
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits", or "license" for more information.
>>> import _hello
>>> _hello.hello("Jared")
'hello Jared'

文件的内容如下:

_hello.c

#include <Python.h>

static PyObject* _hello(PyObject* self, PyObject *args) {
   PyObject* name;
   if (!PyArg_ParseTuple(args, "U", &name)) {
       return NULL; 
   }
   PyObject *ret = PyUnicode_FromFormat("hello %U", name);

   return ret;
}

static struct PyMethodDef methods[] = {
    {"hello", (PyCFunction)_hello, METH_VARARGS},
    {NULL, NULL}
};

static struct PyModuleDef module = {
    PyModuleDef_HEAD_INIT, 
    "_hello",
    NULL, 
    -1, 
    methods
};

PyMODINIT_FUNC PyInit__hello(void) {
    return PyModule_Create(&module);
}

setup.py

from setuptools import setup
from setuptools import Extension

setup(
        name='hello-lib',
        version='1',
        ext_modules=[Extension('_hello', ['_hello.c'])],
        )

有人能否给我一些建议,我做错了什么?是编译还是我编写的代码有问题?任何帮助将不胜感激!

英文:

I've been experimenting with C modules in python and I've had no problems with compilation. However, when it comes to importing the module I receive this error message:

&gt;&gt;&gt; import _strrev
Traceback (most recent call last):
  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
ImportError: /path/to/my/module.so: undefined symbol: strrev

The contents of the file are

_strrev.c

#include &lt;Python.h&gt;
#include &lt;string.h&gt;
static PyObject* _strrev(PyObject* self, PyObject *args) {
   PyObject* name;
   if (!PyArg_ParseTuple(args, &quot;U&quot;, &amp;name)) {
       return NULL; 
   }
   PyObject *ret = strrev(*name); 

   return ret;
}

static struct PyMethodDef methods[] = {
    {&quot;strrev&quot;, (PyCFunction)_strrev, METH_VARARGS},
    {NULL, NULL}
};

static struct PyModuleDef module = {
    PyModuleDef_HEAD_INIT, 
    &quot;_strrev&quot;,
    NULL, 
    -1, 
    methods
};

PyMODINIT_FUNC PyInit__strrev(void) {
    return PyModule_Create(&amp;module);
}

setup.py

from distutils.core import setup, Extension

setup(
        name=&#39;strrev_lib&#39;,
        version=&#39;1&#39;,
        ext_modules=[Extension(&#39;_strrev&#39;, [&#39;_strrev.c&#39;])],
        )

When running nm -D on this object file, I get this output

$ nm -D _strrev.cpython-39-x86_64-linux-gnu.so 
                 w __cxa_finalize@GLIBC_2.2.5
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U PyArg_ParseTuple
00000000000011a0 T PyInit__strrev
                 U PyModule_Create2
                 U __stack_chk_fail@GLIBC_2.4
                 U strrev

I can see that strrev is here, so I don't understand why it says that the symbol in undefined.

I've also tried using a different module and that works perfectly fine when attempting to import it.

$ python3
Python 3.9.2 (default, Feb 28 2021, 17:03:44) 
[GCC 10.2.1 20210110] on linux
Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.
&gt;&gt;&gt; import _hello
&gt;&gt;&gt; _hello.hello(&quot;Jared&quot;)
&#39;hello Jared&#39;

The contents of the files are:
_hello.c

#include &lt;Python.h&gt;

static PyObject* _hello(PyObject* self, PyObject *args) {
   PyObject* name;
   if (!PyArg_ParseTuple(args, &quot;U&quot;, &amp;name)) {
       return NULL; 
   }
   PyObject *ret = PyUnicode_FromFormat(&quot;hello %U&quot;, name);

   return ret;
}

static struct PyMethodDef methods[] = {
    {&quot;hello&quot;, (PyCFunction)_hello, METH_VARARGS},
    {NULL, NULL}
};

static struct PyModuleDef module = {
    PyModuleDef_HEAD_INIT, 
    &quot;_hello&quot;,
    NULL, 
    -1, 
    methods
};

PyMODINIT_FUNC PyInit__hello(void) {
    return PyModule_Create(&amp;module);
}

setup.py

from setuptools import setup
from setuptools import Extension

setup(
        name=&#39;hello-lib&#39;,
        version=&#39;1&#39;,
        ext_modules=[Extension(&#39;_hello&#39;, [&#39;_hello.c&#39;])],
        )

Can anyone give me pointers as to what I'm doing wrong? Is it something with the compilation or with the code that I've written? Any help would be appreciated!

答案1

得分: 1

> 我可以看到 strrev 在这里,所以我不明白为什么它说这个符号未定义。

恰恰相反:您可以看到strrev 不在 那里 - nm 输出中的 U 表示_未定义_。

strrev 似乎是一个Windows的东西,而您不在Windows上。在GLIBC中没有这样的符号:

$ nm -D /lib/x86_64-linux-gnu/libc.so.6 | grep strrev
$

要解决这个问题,您需要自己实现strrev()

英文:

> I can see that strrev is here, so I don't understand why it says that the symbol in undefined.

Au contraire: you can see that strrev is not there -- U in nm output means undefined.

The strrev appears to be a Windows thing, and you are not on Windows. There is no such symbol in GLIBC:

$ nm -D /lib/x86_64-linux-gnu/libc.so.6 | grep strrev
$

To fix this, you would need to implement strrev() yourself.

huangapple
  • 本文由 发表于 2023年5月15日 04:56:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76249640.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定