Reputation: 31
I have a problem with extending python with a simple C file.
hello.c source code:
#include <Python.h>
static PyObject* say_hello(PyObject* self, PyObject* args)
{
const char* name;
if (!PyArg_ParseTuple(args, "s", &name))
return NULL;
printf("Hello %s!\n", name);
Py_RETURN_NONE;
}
static PyMethodDef HelloMethods[] =
{
{"say_hello", say_hello, METH_VARARGS, "Greet somebody."},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC
inithello(void)
{
(void) Py_InitModule("hello", HelloMethods);
}
setup.py:
from distutils.core import setup, Extension
module1 = Extension('hello', sources = ['hello.c'])
setup (name = 'PackageName',
version = '1.0',
packages=['hello'],
description = 'This is a demo package',
ext_modules = [module1])
I also created empty file "__init__.py" in the folder "hello".
After calling "python setup.py build" I could import hello, but when I try to use "hello.say_hello()" I face with the error:
Traceback (most recent call last): File "< stdin>", line 1, in AttributeError: 'module' object has no attribute 'say_hello'
I appreciate if somebody can help me to find the solution.
Thanks
Upvotes: 2
Views: 1782
Reputation: 101959
Your are importing the package instead of the extension:
$python2 hello_setup.py build
running build
running build_py
# etc.
$cd build/lib.linux-x86_64-2.7/
$ls
hello hello.so
$python
Python 2.7.4 (default, Apr 19 2013, 18:28:01)
[GCC 4.7.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import hello
>>> hello
<module 'hello' from 'hello/__init__.py'>
If you want to import the extension, hello.so
, then you have to either rename it, or put it under the package. In which case you can use from hello import hello
to import it:
$mv hello.so hello
$python2
Python 2.7.4 (default, Apr 19 2013, 18:28:01)
[GCC 4.7.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from hello import hello
>>> hello
<module 'hello.hello' from 'hello/hello.so'>
>>> hello.say_hello("World!")
Hello World!!
I don't see the reason to have a package that only contains a single extension module. I'd simply get rid of the package using a simpler setup:
from distutils.core import setup, Extension
module1 = Extension('hello', sources=['hello.c'])
setup(name='MyExtension',
version='1.0',
description='This is a demo extension',
ext_modules=[module1])
This will only produce the hello.so
library, and you can simply do:
>>> import hello
To import the extension.
General advice: avoid having more than one module/package with the same name.
Sometimes it's hard to tell which module is imported(as in your case).
Also, when using different names instead of importing the wrong module and getting weird bugs you'll see an ImportError
if something is wrong, which points out what exactly is missing.
Upvotes: 1