Использование precompiled headers в CMake – 2

Еще один один вариант использования 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 смотрим здесь.

Создание модуля расширения для Python на языке Си

Простой, а главное — рабочий пример модуля расширения на языке 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 на хабре:

P.S. По своему опыту могу сказать, что Boost.Python — редкостное барахло, возьмите лучше библиотеку PyCXX.

Блог Евгения Жирнова