【问题标题】:Error while creating a python binding创建 python 绑定时出错
【发布时间】:2012-03-23 17:57:14
【问题描述】:

这个C语言程序运行和编译良好:

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>

#include <atasmart.h>
int main(){
const char *device = "/dev/sda";
int ret;
 uint64_t ms;
 SkDisk *d;
         if ((ret = sk_disk_open(device, &d)) < 0) {
                        printf("Failed to open disk\n");
                        return 1;
                }





                              if ((ret = sk_disk_smart_read_data(d)) < 0) {
                                printf("Failed to read SMART data: \n");

                        }

                        if ((ret = sk_disk_smart_get_power_on(d, &ms)) < 0) {
                                printf("Failed to get power on time:\n");

                        }

                        printf("%llu\n", (unsigned long long) ms);


            return 0;

}

使用:

gcc atatest.c `pkg-config --cflags --libs libatasmart` 

但是,在尝试基于该程序创建 python 绑定时:

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>

#include <atasmart.h>

#include <Python.h>

 static PyObject *pySmart_powerOn(PyObject *self, PyObject *args)
{
    const char *device = "/dev/sda";
int ret;
 uint64_t ms;
 SkDisk *d;

    if (!PyArg_ParseTuple(args, "s", &device))
    {
        return NULL;
    }

                        if ((ret = sk_disk_smart_get_power_on(d, &ms)) < 0) {
                              return Py_BuildValue("s", "Failed to get power on time");

                        }
            return Py_BuildValue("K", (unsigned long long) ms);
}

static PyMethodDef pySmart_methods[] = {
        { "powerOn", (PyCFunction)pySmart_powerOn, METH_VARARGS, NULL },
        { NULL, NULL, 0, NULL }
};

PyMODINIT_FUNC initpySmart()
{
        Py_InitModule3("pySmart", pySmart_methods, "Trial module");
}

我使用

创建了一个共享库
gcc -shared -I/usr/include/python2.7 `pkg-config --cflags --libs libatasmart` atabind.c -o pySmart.so -fPIC

然后我收到如下警告:,但文件编译

In file included from /usr/include/python2.7/Python.h:8:0,
                 from atabind.c:12:
/usr/include/python2.7/pyconfig.h:1158:0: warning: "_POSIX_C_SOURCE" redefined [enabled by default]
/usr/include/features.h:214:0: note: this is the location of the previous definition

当我在 Python 中运行时

import pySmart

我明白了

ImportError: ./pySmart.so: undefined symbol: sk_disk_smart_get_power_on

我的猜测是错误是因为我编译了带有错误标志/选项的 pySmart.so 共享库..但我无法弄清楚!

【问题讨论】:

    标签: python c gcc binding shared


    【解决方案1】:

    您需要在源文件之后指定链接器标志 (-lfoo)。这是因为链接器的工作方式:当您为它指定一个库时,它会检查库中是否有到目前为止所需的符号。如果不需要符号(好像您还没有访问任何源对象),它只是跳过库。

    试试下面的命令行:

    gcc -shared -I/usr/include/python2.7 \
         `pkg-config --cflags libatasmart` \
         atabind.c \
         `pkg-config --libs libatasmart` \
         -o pySmart.so -fPIC
    

    【讨论】:

    • 当你厌倦了手工操作之后,开始使用 distutils 代替:docs.python.org/dist
    • @ThomasWouters,我完全同意。然而,手工做事有时具有很好的教育性质。 ;)
    • 确实如此。因此“在你累了之后”:)
    • 非常感谢,它成功了。将在其他所有内容之前指定源文件。第一次这样做,因此手动......从现在开始打算使用distutils。谢谢!
    【解决方案2】:

    您应该先包含您的 Python.h,然后再包含任何 std 标头。

    使用 Python/C API 所需的所有函数、类型和宏定义都包含在您的代码中

    #include "Python.h"

    这意味着包含以下标准标头: &lt;stdio.h&gt;, &lt;string.h&gt;, &lt;errno.h&gt;, &lt;limits.h&gt;, &lt;assert.h&gt; and &lt;stdlib.h&gt;(如果有)。

    由于 Python 可能会定义一些预处理器定义,这些定义会影响某些系统上的标准头文件,因此您必须在包含任何标准头文件之前包含 Python.h。

    或者: 只是 _GNU_SOURCE ,它将被 GNU libc 的 /usr/include/features.h 忽略

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-07
      • 1970-01-01
      • 1970-01-01
      • 2017-07-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多