Простой, а главное — рабочий пример модуля расширения на языке C для питона. Модуль называется example, а реализовывает одну функцию hello, которая вызывается с параметром who и возвращает «Hello %s» % who.
Листинг модуля example.c
Python 2.xx
#include <Python.h> PyObject *hello( PyObject *self, PyObject *args, PyObject *kwargs ) { char *who = 0; static char *keywords[] = {"who", NULL}; PyObject *result = 0; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", keywords, &who)) { return NULL; } result = PyString_FromString("Hello "); PyString_Concat(&result, PyString_FromString(who)); return result; } static PyMethodDef example_methods[] = { { "hello", (PyCFunction) hello, METH_KEYWORDS, "hello(who) -- return \"Hello who\"" }, { NULL, 0, 0, NULL } }; PyMODINIT_FUNC initexample() { (void) Py_InitModule("example", example_methods); if (PyErr_Occurred()) { PyErr_SetString(PyExc_ImportError, "example module init failed"); } } |
Python 3.xx
#include <Python.h> PyObject *hello( PyObject *self, PyObject *args, PyObject *kwargs ) { char *who = 0; static char *keywords[] = {"who", NULL}; if (PyArg_ParseTupleAndKeywords(args, kwargs, "s", keywords, &who)) { return PyUnicode_FromFormat("Hello %s", who); } return NULL; } static PyMethodDef example_methods[] = { { "hello", (PyCFunction) hello, METH_KEYWORDS, "hello(who) -- return \"Hello who\"" }, { NULL, 0, 0, NULL } }; static struct PyModuleDef example_module = { PyModuleDef_HEAD_INIT, "example", NULL, -1, example_methods }; PyMODINIT_FUNC PyInit_example(void) { return PyModule_Create(&example_module); } |
Листинг setup.py
setup.py
from distutils.core import setup from distutils.extension import Extension examplemodule = Extension(name="example", sources=['example.c', ]) setup(name="example", ext_modules=[examplemodule]) |
Компилируем:
python setup.py build |
Инсталлируем:
python setup.py install |
Выполняем простенький тест:
from example import hello print hello(who="world!") |
Радуемся :)
Hello world! |
Полезные ссылки (на английском):
Цикл статей про Boost.Python на хабре:
- Объединяя C++ и Python. Тонкости Boost.Python. Часть первая
- Объединяя C++ и Python. Тонкости Boost.Python. Часть вторая
- Конвертация типов в Boost.Python. Делаем преобразование между привычными типами C++ и Python
- Путешествие исключений между C++ и Python или «Туда и обратно»
P.S. По своему опыту могу сказать, что Boost.Python — редкостное барахло, возьмите лучше библиотеку PyCXX.
Спасибо!
Я бы еще добавил перед «Выполняем простенький тест» раздел «Инсталлируем» с одной строчкой —
[sudo] python setup.py install
И еще интересно как можно собранный у меня на машине пакет инсталлировать на компьютер клиента?
т.е. прокатит ли в скрипте инсталляции моей программы прописать строчку
python setup.py install
чтобы потом использовать данный пакет в своей программе?
Спасибо за дополнение. Обновил запись.
По поводу инсталляции — никогда не возникало такой необходимости, но вот эта команда должна создавать инсталляционный пакет (можно выбрать tgz, zip, rpm и инсталлятор для win32):
Вот здесь можно найти подробности: http://docs.python.org/distutils/builtdist.html
А вот здесь можно узнать, как работать с получившимся пакетом: http://docs.python.org/install/index.html
Проверил, работает. Вместо всяког хабраклала.
Рекомендую библиотеку PyCXX для Python функций из C++ и наоборот.
а у меня чего-то с такой ошибкой вываливается…
Сложно сказать по такой ошибке что происходит. Вы пишете это в файле или в интерпретаторе?
Нашел ваш пост тут: http://python.su/forum/topic/25437/
У меня на FreeBSD все нормально завелось, возможно проблема на вашей стороне.
В первом листинге опечатка нужно PyMODINIT_FUNC вместо PYMODINIT_FUNC
Спасибо! Исправил.
Норм. Спасибо!
Я совместно юзаю cython. Пишу на питоне Модуль, после перегоняю его в СИ «cython -3 —no-docstrings *.pyx», а дальше все как в Вашей статье. Получаю *.pyd а дальше pyinstaller в дело. Вот такие пироги =)))
Остался вопрос для успокоения души… Так ли просто теперь хакнуть мой *.pyd и добраться до исходников питона?