1

This program in C runs and compiles well :

#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;

}

using:

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

However while trying to create python bindings based on that program:

#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");
}

I create a shared library using

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

then I get a warning as follows :, but the file compiles

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

when in Python i run

import pySmart

I get

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

My guess is that the error is caused because I have compiled the pySmart.so shared library with incorrect flags/options.. but I'm unable to figure it out!

2 Answers 2

2

You need to specify linker flags (-lfoo) after your source files. That's because of the way how linker works: when you specify a library to it, it checks the library for symbols needed so far. If no symbols needed (as if you didn't get to any source objects yet), it just skips the library.

Try the following commandline:

gcc -shared -I/usr/include/python2.7 \
     `pkg-config --cflags libatasmart` \
     atabind.c \
     `pkg-config --libs libatasmart` \
     -o pySmart.so -fPIC
Sign up to request clarification or add additional context in comments.

4 Comments

And after you get tired of doing this by hand, start using distutils instead: docs.python.org/dist
@ThomasWouters, I do absolutely agree. However, doing things manually sometimes has very good educative properties. ;)
Indeed. Hence "after you get tired" :)
Thanks a lot, it worked. Will specify source files before everything else. Was doing it for the first time, hence manually... Do intend to use distutils from now on. Thanks!
1

You should include your Python.h first then any std header.

All function, type and macro definitions needed to use the Python/C API are included in your code by

#include "Python.h"

This implies inclusion of the following standard headers: <stdio.h>, <string.h>, <errno.h>, <limits.h>, <assert.h> and <stdlib.h> (if available).

Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included.

Alternatively: just _GNU_SOURCE , and it will be ignored by GNU libc's /usr/include/features.h

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.