boost.python小试牛刀

boost.python官网: http://www.boost.org/doc/libs/1_55_0/libs/python/doc/

这里的例子不错:http://en.wikibooks.org/wiki/Python_Programming/Extending_with_C%2B%2B

makefile(暂记,没用过):http://www.shocksolution.com/python-basics-tutorials-and-examples/linking-python-and-c-with-boostpython/

一些用法可参考机器人项目中的“封拆包worldpacket”和“解析地图文件mapparse”

1.搭建环境(官网都有文档):   

wget http://sourceforge.net/projects/boost/files/boost/1.55.0/boost_1_55_0.tar.gz/download
tar zvxf boost_1_55_0.tar.gz
./bootstrap.sh --help
./bootstrap.sh --show-libraries
./bootstrap.sh --with-libraries=python,regex --with-python-root=/home/dongsong/venv/bin/python --prefix=/usr/local/boost
sudo ./b2 install
[dongsong@localhost tutorial]$ pwd
/home/dongsong/boost_1_55_0/libs/python/example/tutorial
[dongsong@localhost tutorial]$ ls -lhrt
总用量 12K
-rwxr-xr-x. 1 dongsong dongsong  275 11月 26 2007 hello.py
-rw-r--r--. 1 dongsong dongsong  484 11月 26 2007 hello.cpp
-rw-r--r--. 1 dongsong dongsong 1.6K 10月 28 05:10 Jamroot
[dongsong@localhost tutorial]$ cat hello.cpp 
//  Copyright Joel de Guzman 2002-2004. Distributed under the Boost
//  Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt
//  or copy at http://www.boost.org/LICENSE_1_0.txt)
//  Hello World Example from the tutorial
//  [Joel de Guzman 10/9/2002]

#include 
#include 

char const* greet()
{
   return "hello, world";
}

BOOST_PYTHON_MODULE(hello_ext)
{
	using namespace boost::python;
	def("greet", greet);
}

[dongsong@localhost tutorial]$ cat hello.py 
#  Copyright Joel de Guzman 2002-2007. Distributed under the Boost
#  Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt
#  or copy at http://www.boost.org/LICENSE_1_0.txt)
#  Hello World Example from the tutorial

import hello_ext
print hello_ext.greet()
[dongsong@localhost tutorial]$ cat Jamroot 
# Copyright David Abrahams 2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

import python ;

if ! [ python.configured ]
{
	ECHO "notice: no Python configured in user-config.jam" ;
	ECHO "notice: will use default configuration" ;
	using python ;
}

# Specify the path to the Boost project.  If you move this project,
# adjust this path to refer to the Boost root directory.
use-project boost
  : ../../../.. ;

# Set up the project-wide requirements that everything uses the
# boost_python library from the project whose global ID is
# /boost/python.
project
  : requirements /boost/python//boost_python 
				 /boost//headers 
  : usage-requirements /boost//headers 
  ;

# Declare the three extension modules.  You can specify multiple
# source files after the colon separated by spaces.
python-extension hello_ext : hello.cpp ;

# Put the extension and Boost.Python DLL in the current directory, so
# that running script by hand works.
install convenient_copy 
  : hello_ext 
  : on SHARED_LIB PYTHON_EXTENSION 
	. 
  ;

# A little "rule" (function) to clean up the syntax of declaring tests
# of these extension modules.
local rule run-test ( test-name : sources + )
{
	import testing ;
	testing.make-test run-pyd : $(sources) : : $(test-name) ;
}

# Declare test targets
run-test hello : hello_ext hello.py ;
[dongsong@localhost tutorial]$ sudo ~/boost_1_55_0/bjam 
link.jam: No such file or directory
...patience...
...patience...
...found 1677 targets...
...updating 15 targets...
common.mkdir bin
common.mkdir bin/gcc-4.4.7
common.mkdir bin/gcc-4.4.7/debug
gcc.compile.c++ bin/gcc-4.4.7/debug/hello.o
gcc.link.dll bin/gcc-4.4.7/debug/hello_ext.so
common.copy libboost_python.so.1.55.0
ln-UNIX libboost_python.so
ln-UNIX libboost_python.so.1
ln-UNIX libboost_python.so.1.55
common.copy hello_ext.so
common.mkdir bin/hello.test
common.mkdir bin/hello.test/gcc-4.4.7
common.mkdir bin/hello.test/gcc-4.4.7/debug
capture-output bin/hello.test/gcc-4.4.7/debug/hello
**passed** bin/hello.test/gcc-4.4.7/debug/hello.test
...updated 15 targets...
[dongsong@localhost tutorial]$ tree -a
.
├── bin
│?? ├── config.log
│?? ├── gcc-4.4.7
│?? │?? └── debug
│?? │??     ├── hello_ext.so
│?? │??     └── hello.o
│?? ├── hello.test
│?? │?? └── gcc-4.4.7
│?? │??     └── debug
│?? │??         ├── hello
│?? │??         ├── hello.output
│?? │??         └── hello.test
│?? └── project-cache.jam
├── hello.cpp
├── hello_ext.so
├── hello.py
├── Jamroot
├── libboost_python.so -> libboost_python.so.1.55.0
├── libboost_python.so.1 -> libboost_python.so.1.55.0
├── libboost_python.so.1.55 -> libboost_python.so.1.55.0
└── libboost_python.so.1.55.0

6 directories, 15 files
[dongsong@localhost tutorial]$ ldd hello_ext.so
		linux-vdso.so.1 =>  (0x00007fff1c3ff000)
		libboost_python.so.1.55.0 => not found
		libutil.so.1 => /lib64/libutil.so.1 (0x00007fef3c9bd000)
		libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fef3c7a0000)
		libdl.so.2 => /lib64/libdl.so.2 (0x00007fef3c59c000)
		libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007fef3c295000)
		libm.so.6 => /lib64/libm.so.6 (0x00007fef3c011000)
		libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fef3bdfb000)
		libc.so.6 => /lib64/libc.so.6 (0x00007fef3ba66000)
		/lib64/ld-linux-x86-64.so.2 (0x00000035b4000000)
[dongsong@localhost tutorial]$ python hello.py 
Traceback (most recent call last):
  File "hello.py", line 6, in 
	import hello_ext
ImportError: libboost_python.so.1.55.0: cannot open shared object file: No such file or directory
[dongsong@localhost tutorial]$ export LD_LIBRARY_PATH=/home/dongsong/boost_1_55_0/libs/python/example/tutorial/
[dongsong@localhost tutorial]$ ldd hello_ext.so 
	linux-vdso.so.1 =>  (0x00007fff6cbff000)
	libboost_python.so.1.55.0 => /home/dongsong/boost_1_55_0/libs/python/example/tutorial/libboost_python.so.1.55.0 (0x00007feec7e7e000)
	libutil.so.1 => /lib64/libutil.so.1 (0x00007feec7c6a000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007feec7a4d000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007feec7849000)
	libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007feec7542000)
	libm.so.6 => /lib64/libm.so.6 (0x00007feec72be000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007feec70a8000)
	libc.so.6 => /lib64/libc.so.6 (0x00007feec6d13000)
	/lib64/ld-linux-x86-64.so.2 (0x00000035b4000000)
[dongsong@localhost tutorial]$ python hello.py 
hello, world
[dongsong@localhost tutorial]$ python
Python 2.6.6 (r266:84292, Jan 22 2014, 09:42:36) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import hello_ext
>>> dir(hello_ext)
['__doc__', '__file__', '__name__', '__package__', 'greet']
>>> hello_ext.greet()
'hello, world'
    

上面已经可以使用了,只是有些不便,今天(2014.6.24)补充一下:

每次export LD_LIBRARY_PATH极其不方便,可以把boost_python.so的路径加到系统路径里去(/etc/ld.so.conf),参见shell手册

把so文件copy到项目代码里面去也不是规范的做法,还是应该像普通python模块一样安装到python的库里面去,按照下面的格式编写setup.py,然后python setup.py install即可(python setup.py build会在当前目录下建立build目录并放置目标so文件,如果不想安装到python库也可以build以后拿生成的so文件用)。include_dirs,library_dirs这些选项可以参见distutils的官方文档,都有详细说明,极其方便。

[dongsong@localhost tutorial]$ cat setup.py 
#!/usr/bin/env python
 
from distutils.core import setup
from distutils.extension import Extension
 
setup(name="hello_ext",
    ext_modules=[
        Extension("hello_ext", ["hello.cpp"],
        include_dirs=["/usr/local/boost/include/"],
        library_dirs = ["/usr/local/boost/lib/"],
        libraries = ["boost_python"])
    ])

2.文档
    个人疑问:const引用传参的接口暴露有什么不一样吗?属性方法调用时候申请堆内存并把地址返回的情况下,是否必须提供释放内存的接口并暴露给外界显式调用?构造函数内开辟的堆内存在析构函数中务必释放这个应该是不变且会被Python解释器正确执行的吧?
    
    构造函数
        class_("World", init())
            .def(init())
            .def("greet", &World::greet)
            .def("set", &World::set);
        class_("Abstract", no_init);
    数据成员
        class_("Var", init())
            .def_readonly("name", &Var::name)
            .def_readwrite("value", &Var::value);
    属性方法
        class_("Num")
            .add_property("rovalue", &Num::get)
            .add_property("value", &Num::get, &Num::set);
    继承
        class_("BaseName") /*...*/ ;
        class_ >("DerivedName") /*...*/ ;
        // Tell Python to take ownership of factory's result, 工厂方法,创建子类实例并把子类指针返回赋值给父类指针,具体见官方文档
        def("factory", factory,
            return_value_policy());
    虚函数
        需要包装,具体见官方文档
    
    引用
        with_custodian_and_ward<1, 2> 第一个参数的生命周期依赖于第二个参数
        return_internal_reference<1.. 第一个参数是返回值(引用)的拥有者
        more is here: http://www.boost.org/doc/libs/1_55_0/libs/python/doc/v2/reference.html#models_of_call_policies

    重载(默认参数)
        BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 1, 4)
        def("foo", foo, foo_overloads());
        ------------------------------------------------------------------------------------
        BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 0, 3)
        .def("foo", (void(*)(bool, int, char))0, foo_overloads());
        ------------------------------------------------------------------------------------
        BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(george_overloads, wack_em, 1, 3)
        .def("wack_em", &george::wack_em, george_overloads());
        ------------------------------------------------------------------------------------
        BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(xf_overloads, f, 1, 3)  混搭,(int,double,char)支持1~3个参数,(int,int,int)必须三个参数
        bool    (X::*fx1)(int, double, char)    = &X::f;
        int     (X::*fx2)(int, int, int)        = &X::f;
        .def("f", fx1, xf_overloads());
        .def("f", fx2)
        ------------------------------------------------------------------------------------
        .def(init >())   带默认参数的构造函数
    
    c/c++中嵌入Python
        1>#include
        2>Call Py_Initialize() to start the interpreter and create the __main__ module.
        3>Call other Python C API routines to use the interpreter.
        执行Python代码:
            object eval(str expression, object globals = object(), object locals = object())
            object exec(str code, object globals = object(), object locals = object())
            object exec_file(str filename, object globals = object(), object locals = object())
        示例:
            object main_module = import("__main__");
            object main_namespace = main_module.attr("__dict__");
            object ignored = exec("result = 5 ** 2", main_namespace);

            int five_squared = extract(main_namespace["result"]);

你可能感兴趣的:(编程语言-c/c++,业务-游戏,编程语言-python)