Еще один один вариант использования precompiled headers в CMake. Подсмотрено в Ogre3D:
#------------------------------------------------------------------- # This file is part of the CMake build system for OGRE # (Object-oriented Graphics Rendering Engine) # For the latest info, see http://www.ogre3d.org/ # # The contents of this file are placed in the public domain. Feel # free to make use of it in any way you like. #------------------------------------------------------------------- ################################################################## # Support macro to use a precompiled header # Usage: # use_precompiled_header(TARGET HEADER_FILE SRC_FILE) ################################################################## macro(use_precompiled_header TARGET HEADER_FILE SRC_FILE) get_filename_component(HEADER ${HEADER_FILE} NAME) if (MSVC) add_definitions(/Yu"${HEADER}") set_source_files_properties(${SRC_FILE} PROPERTIES COMPILE_FLAGS /Yc"${HEADER}" ) elseif (CMAKE_COMPILER_IS_GNUCXX) # disabled because it seems to increase compile time ## this is some serious hack... we definitely need native ## support in CMake for this! ## we will generate the precompiled header via a workaround ## first give the header a new name with the proper extension #set(PRECOMP_HEADER ${CMAKE_CURRENT_BINARY_DIR}/hacked/${HEADER}.gch) #configure_file(${HEADER_FILE} ${PRECOMP_HEADER} COPYONLY) ## retrieve some info about the target's build settings #get_target_property(${TARGET} PRECOMP_TYPE TYPE) #if (PRECOMP_TYPE STREQUAL "SHARED_LIBRARY") # set(PRECOMP_LIBTYPE "SHARED") #else () # set(PRECOMP_LIBTYPE "STATIC") #endif () #get_target_property(${TARGET} PRECOMP_DEFINITIONS COMPILE_DEFINITIONS) #get_target_property(${TARGET} PRECOMP_FLAGS COMPILE_FLAGS) # ## add a new target which compiles the header #add_library(__precomp_header ${PRECOMP_LIBTYPE} ${PRECOMP_HEADER}) #add_dependencies(${TARGET} __precomp_header) #set_target_properties(__precomp_header PROPERTIES # COMPILE_DEFINITIONS ${PRECOMP_DEFINITIONS} # COMPILE_FLAGS ${PRECOMP_FLAGS} # HAS_CXX TRUE #) #set_source_files_properties(${PRECOMP_HEADER} PROPERTIES # HEADER_FILE_ONLY FALSE # KEEP_EXTENSION TRUE # COMPILE_FLAGS "-x c++-header" # LANGUAGE CXX #) # ## finally, we need to ensure that gcc can find the precompiled header ## this is another dirty hack #include_directories(BEFORE "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/__precomp_header.dir/hacked") endif () endmacro(use_precompiled_header) |
Использование также тривиально:
FILE( GLOB_RECURSE SRC *.cpp ) USE_PRECOMPILED_HEADER( projectName "precompiled.h" "precompiled.cpp" ) |
UPDATE: Окончательный вариант precompiled headers смотрим здесь.
Простой, а главное — рабочий пример модуля расширения на языке 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.
Определитель матрицы 3×3 вычисляется следующим образом: