??xml version="1.0" encoding="utf-8" standalone="yes"?>久久久WWW免费人成精品,99久久国产精品免费一区二区,久久久精品无码专区不卡http://www.shnenglu.com/Squirrel/category/1771.html始有道,道生时空。时I,~程之阴队뀂不得道者失时空Q得道者时I盈余以完工。其有异乎?zh-cnMon, 19 May 2008 14:47:12 GMTMon, 19 May 2008 14:47:12 GMT60[转蝲]用Boost.Python构徏混合pȝ http://www.shnenglu.com/Squirrel/archive/2006/05/15/7193.htmlSquirrelSquirrelMon, 15 May 2006 07:44:00 GMThttp://www.shnenglu.com/Squirrel/archive/2006/05/15/7193.htmlhttp://www.shnenglu.com/Squirrel/comments/7193.htmlhttp://www.shnenglu.com/Squirrel/archive/2006/05/15/7193.html#Feedback2http://www.shnenglu.com/Squirrel/comments/commentRss/7193.htmlhttp://www.shnenglu.com/Squirrel/services/trackbacks/7193.html

目录

摘要

BoostQPython是一个开源的C++E序库,提供cMIDL的接口来把C++cd函数l定到Python。借助于C++强大的编译时内省(introspection)能力和最新的元编E?metaprogramming)技术,它完全用C++来实玎ͼ而不用引入新的语法。Boost.Python丰富的特性和高接口使从底层h混合pȝ的方式设计组件成为可能,从而ɽE序员可以轻村֒q诏的同时用C++高效的编译时多态和Python极其方便的运行时多态?/p>

?/a>

作ؓ两门语言Qpython和C++在很多方面不一栗C++被编译ؓ机器码,python被解?interpreted)执行。Python的动态类?type)pȝl常被认为是灉|性的基础QC++的静态类型是效率的基矟뀂C++有复杂艰q~译时元语言(meta-language)Q而在python里,实际上一切都在运行时发生。然而对很多E序员来_q些不同恰好意味着Python和C++是彼此的完美补。Python E序里的性能瓉部分可以用C++来重写,从而最大化速度。强大的C++E序库的作者选择Python作ؓ中间?middleware)语言Q从而获得灵zȝpȝ集成能力。此外,表面的不同掩盖了二者非常类似的一些地方:

考虑到Python丰富的’C'协作APIQ原则上把C++的类型和函数以类g暴露lC++的接口暴露给Python是可能的。然而,单是Python提供的这U设施对集成C++的支持比较弱。和C++QPython相比Q’C'的抽象机刉常初U,而且完全不支持异常处理。’C'扩展模块的作者必L动管理引用计敎ͼq不但让人恼火的ȝ和单调,q极度容易出错。传l的扩展模块Ҏ产生重复的样板代?boilerplate code)Q从而难于维护,其是要包装的API很复杂时?/p>

上述限制D了一些包装系l的开发。SWIG_ 可能是集成C/C++和Python的包装系l中最行的。一个更q的例子?SIP Q它专门设计来提?Qt 囑Ş用户界面库的Python接口。SWIG和SIP都引入了它们专有的语a来实现语a间绑定。这当然有它的好处,但不得不应付三种不同的语a(PythonQC/C++和接口语a)也带来了实际的和心理上的困难?CXX 软g包展C出它是一个有的包装pȝ。它说明了至一部䆾Python ‘C?API可以通过用户友好得多的C++接口来包装和表现。然而,和SWIG和SIP不一PCXX不支持把C++cd装成新的Pythoncd?/p>

Boost.Python 的特性和目标和很多这Lpȝ有相当程度的重叠。就是说QBoost.Python试图最大化便利性和灉|性,而不引入单独的包装语a。相反,它在q后用静态元~程技术管理很多复杂问题,赋予了用户通过高C++接口来包装C++cd函数的能力,Boost.Python也在如下领域越了早期的pȝQ?/p>

  • C++虚函数支持,虚函数可以用Python来覆?override)
  • 在整个生命周期内对低U指针和引用q行全面理的设?
  • Ҏ扩展(extensions)l织成Python packages的支持,通过中心注册?central registry)来进行语a间类型{?
  • 安全而便利的q接强大的Python序列化引?pickle)的机?
  • C++的lvalue和rvalue的一致的处理规则Q这只能来自对Python和C++两者的cdpȝ的深入理解?

鼓舞Boost.Python开发的关键发现是,传统扩展开发中的大量样板代码都可以通过C++~译时内省来消除。被包装的C++函数的每个参数都必须Ҏ参数cd从Python对象里取出来。类似地Q函数返回值的cd军_了返回值如何从C++转换成Python。参数类型和q回值类型当焉是每个函数的cd的一部分Q正是从q里QBoost.Python推导Z大部分需要的信息?/p>

q种Ҏ导向?用户引导的包?/em> Q尽可能的用UC++的框架直接从要包装的代码里取得信息,q以外的信息qh式提供。大多数引导是自动的Q很需要真正的q涉。因为写接口规范和写被暴露的代码的是同一门全功能语言Q当需要取得控制时用户有了I前强大的能力?/p>

Boost.Python 设计目标

Boost.Python的首要目标是让用户只用C++~译器就能向Python暴露C++cd函数。大体来Ԍ允许用户直接从Python操作C++对象?/p>

然而,有一点很重要Q那是不要 q于 按字面翻译所有接口:必须考虑每种语言的惯用语。例如,虽然C++和Python都有q代器的概念Q表达方式却很不一栗Boost.Python必须能连接这些不同的接口?/p>

必须把Python用户和C++接口的微误用造成的崩溃隔R出于同样原因,应该把C++用户和低UPython ‘C?API隔离Q容易出错的C接口Q比如手动引用计数管理,原始?raw)PyObject指针Q应该用更加健壮?more-robust)替代物来取代?/p>

支持Zlg的开发是臛_重要的,因此被暴露在一个扩展模块里的C++cd应该能够被传递给被暴露在另一个模块中的函敎ͼ而不丢失重要的信息,比如说C++l承关系?/p>

最后,所有的包装必须?非R入的(non-intrusive) Q不能修改甚至看不到原始的C++代码。对只能看见它头文g和二q制文g的第三方Q现有的C++库必L可包装的?/p>

Hello Boost.Python World

现在来预览一下Boost.PythonQƈ看看它如何改qPython的原始包装功能。下面是我们x露的一个函?

char const* greet(unsigned x)
{
   static char const* const msgs[] = { "hello"Q?Boost.Python"Q?world!" };

   if (x > 2)
       throw std::range_error("greet: index out of range");

   return msgs[x];
}

用Python的C API和标准C++来包装这个函敎ͼ我们需要像q样:

extern "C" // 所有Python交互都用C链接和调用习?
{
    // 处理参数/l果转换和检查的包装?
    PyObject* greet_wrap(PyObject* argsQPyObject * keywords)
    {
         int x;
         if (PyArg_ParseTuple(argsQ?i"Q?amp;x))    // 取出/查参?
         {
             char const* result = greet(x);      // 调用被包装的函数
             return PyString_FromString(result); // l果转换成Python
         }
         return 0;                               // 发生了错?
    }

    // 待包装函数表Q函数用q个模块来暴?
    static PyMethodDef methods[] = {
        { "greet"Qgreet_wrapQMETH_VARARGSQ?return one of 3 parts of a greeting" }
        Q{ NULLQNULLQ?QNULL } // sentinel
    };

    // 模块初始化函?
    DL_EXPORT init_hello()
    {
        (void) Py_InitModule("hello"Qmethods); // d成员函数(method)到模?
    }
}

现在看看我们使用Boost.Python来暴露它时的包装代码:

#include <boost/python.hpp>
using namespace boost::python;
BOOST_PYTHON_MODULE(hello)
{
    def("greet"QgreetQ?return one of 3 parts of a greeting");
}

下面是用它的代?

>>> import hello

>>> for x in range(3):
...     print hello.greet(x)
...
hello
Boost.Python
world!

C API版本要冗长的多,此外Q一些它没有正确处理的地方值得提到Q?/p>

  • 原来的函数接受无W号整数QPython ‘C?API仅仅提供了提取有W号整数的方式。如果我们试囑֐hello.greet传递负数Boost.Pyt hon版将抛出Python异常Q而Python ‘C?API版则会l像在C++实现中那栯{换负数到无符h(通常包装成某U很大的?Q然?把不正确的{换结果传l被包装函数?
  • q引起了W二个问题:如果函数的参数大?QC++ greet()被调用时会抛出异常。典型的Q如果C++异常跨越C~译器生成的代码?边界传递,会导致崩溃。正如你在第一个版本中看到的,那儿没有C++脚手?scaffolding)来防止崩溃发生。被Boost.Python包装 q的函数自动包含了异常处理层Q它把未处理的C++异常译成相应的Python异常Q从而保护了Python用户?
  • 一个更微妙的限制是QPython ‘C?API的参数{换机制只能以一U方式取得整数x。如果一个Python long 对象(L_ֺ整数) y可以转换?fit in)unsigned int而不能{换成signed longQPyArg_ParseTuple不能对其q行转换。同样如果被包装的C++ cd含用户定义的隐式operator unsigned int()转换Q它永远不能处理。Boost.Python的动态类型{换注册表允许用户Ld 转换Ҏ?

库概?/a>

q部分简要描qC库的主要Ҏ。ؓ了避免؜淆,忽略了实现细节?/p>

暴露c?Exposing Classes)

C++cdl构以类似的z的接口来暴霌Ӏ假设有:

struct World
{
    void set(std::string msg) { this->msg = msg; }
    std::string greet() { return msg; }
    std::string msg;
};

下面的代码将在我们的扩展模块里暴露它:

#include <boost/python.hpp>

BOOST_PYTHON_MODULE(hello)
{
    class_<World>("World")
        .def("greet"Q?amp;World::greet)
        .def("set"Q?amp;World::set)
    ;
}

管上述代码有某U熟悉的Pythonic的感觉,但语法有时还是有点o惑,因ؓ它看h不像Z习惯的C++代码。但是,q仍然只是标准C++。因为它们灵zȝ语法和操作符重蝲QC++和Python都很适于定义特定领域(?语言( domain-specific (sub)languages) (DSLs)。那是我们在Boost.Python里所做的。把代码拆开来看:

class_<World>("World")

构造类型class_<World>的未命名对象Q把"World"传给它的构造器。这在扩展模块里创Z个叫World的new-style Pythonc,q把它和C++cdWorld在Boost.Python的类型{换注册表里关联v来。我们也可以q么?

class_<World> w("World");

但那样做的话会更J琐Q因为我们不得不再次命名w以调用它的def()成员函数:

w.def("greet"Q?amp;World::greet)

原来的例子里表示成员q入的点的位|没有什么特别的QC++允许L的空白符出现在表意符?token)的Q一边,把点攑֜每行的开始允许用l一的语法把q箋的调用都串v来,不管我们想串多少都行。另一个允许的串接的事实是class_<>成员函数都返回对*this的引用?/p>

因此原来的例子等同于:

class_<World> w("World");
w.def("greet"Q?amp;World::greet);
w.def("set"Q?amp;World::set);

能这h分Boost.Pythoncd装层的组成部分有时候是有用的,但本文的剩下部分一直用简z的语法?/p>

最后来看包装类被用的情况:

>>> import hello
>>> planet = hello.World()
>>> planet.set('howdy')
>>> planet.greet()
'howdy'

构造器(Constructors)

因ؓ我们的Worldcd是一个简单的structQ它有一个隐式的无参?no-argument)(nullary)构造器。Boost.Python默认暴露nullary构造器Q这是我们可以像下面这样写的原?

>>> planet = hello.World()

然而不哪门语aQ设计得好的cd能都需要构造器参数Q以建立他们的不变量(invariants)。在Python里,__init__只是一个特D名U的成员函数(method)Q与q不同,C++里的构造器不能像普通成员函数那样处理。特别是我们不能取它的地址: &World::Worldq样会被报错。库提供了一个不同的接口来指定构造器。假设有:

struct World
{
    World(std::string msg); // d的构造器
    ...

我们可以q样修改包装代码:

class_<World>("World"Qinit<std::string>())
    .def(init<doubleQdouble>())
    ...

当然QC++cd能还有其他的构造器Q我们也可以暴露他们Q只需要向def()传递更多init<?gt;的实?

class <World>("World"Qinit<std::string>())
        .def(init<doubleQdouble>())
        ...

Boost.Python允许被包装的函数Q成员函C及构造器被重载,以映C++重蝲?/p>

数据成员和属?Properties)

C++中的M可公q讉K的数据成员都能轻易的被包装成只读或者只写属?attributes):

class_<World>("World"Qinit<std::string>())
    .def_readonly("msg"Q?amp;World::msg)
    ...

q直接在Python里?

>>> planet = hello.World('howdy')
>>> planet.msg
'howdy'

q不会导致添加属性到World实例__dict__Q从而在包装大型数据l构时节省大量的内存。实际上Q除非从Python昑ּd属性,否则实例__dict__Ҏ不会被创建。Python的这U能力来源于新的Python 2.2 cdpȝQ尤其是descriptor接口和propertycd?/p>

在C++里,可公q讉K的数据成员被认ؓ是糟p设计的表现Q因Z们破坏了装(encapsulation)Q文体向?style guides)通常指示代之?getter" ?"setter"函数。然而在Python里,__getattr__Q__setattr__和从2.2开始有的property意味着属性进入只是程序员控制下的装得更好的语法工具。通过让Python property对用L接可用,Boost.Pythonq接了二者的不同惯用语。如果msg是私有的Q我们仍然能把它暴露为Python里的属?

class_<World>("World"Qinit<std::string>())
    .add_property("msg"Q?amp;World::greetQ?amp;World::set)
    ...

上面的例子映了Z熟悉的Python 2.2+里的property用法:

>>> class World(object):
...     __init__(selfQmsg):
...         self.__msg = msg
...     def greet(self):
...         return self.__msg
...     def set(selfQmsg):
...         self.__msg = msg
...     msg = property(greetQset)

操作W重?/a>

能给用户定义cd定义术操作W一直是两门语言的数D取得成功一个重要因素。像 Numpy q样的Y件包的成功证明了在扩展模块中暴露操作W能产生巨大能量。Boost.Pythonl包装操作符重蝲提供了简z的机制。下面是包装Boost的有理数? rational number library)的代码的片断:

class_<rational<int> >("rational_int")
  .def(init<intQint>()) // constructorQe.g. rational_int(3Q?)
  .def("numerator"Q?amp;rational<int>::numerator)
  .def("denominator"Q?amp;rational<int>::denominator)
  .def(-self)        // __neg__ (unary minus)
  .def(self + self)  // __add__ (homogeneous)
  .def(self * self)  // __mul__
  .def(self + int()) // __add__ (heterogenous)
  .def(int() + self) // __radd__

q种法是通过单的应用"表达式模?("expression templates") [VELD1995] 来施加的Q?表达式模?是一U最初ؓ优化高性能矩阵代数表达式而开发的技术。本质是不立卌行计,而重载操作符来构造描q计的cd。在矩阵代数里,当考虑整个表达式的l构Q而不?贪婪?Ҏ步操作求值时Q经常可以获得戏剧性的优化。Boost.Python用同L技术来构徏Z包含 self 的表辑ּ的适当的Python 成员函数对象(method object)?/p>

l承

要在Boost.Python里描qC++l承关系Q可以像下面q样把可选的bases<?gt;参数d到class_<?gt;模板参数表里:

class_<DerivedQbases<Base1QBase2> >("Derived")
     ...

q样有两个效果:

  1. 当class_<?gt;被创建时Q在Boost.Python的注册表里查扑֯应于Base1和Base2的Pythoncd对象Q然后作为新的Python衍生c?型对象的基类。因而暴露给Base1和Base2的成员函数自动成Z衍生cd的成员。因为注册表是全局的,即暴露衍生cd的模 块和它的M基类的模块不同,l承同样有效?
  2. 衍生cd基类的C++转换被添加到Boost.Python注册表。因此期待Q一基类对象(的指针或引用)的被包装C++成员函数可以被包?了Q一基类的衍生实例的对象调用。类T的被包装成员函数被视为具有隐式的W一个参数T&Q那么ؓ了让衍生对象能调用基cL 员函敎ͼq些转换是必需的?

当然从被包装的C++cd例衍生新的PythoncL可能的。这是因为Boost.Python使用了new-style classpȝQ这套系l在Python内置cd上工作良好。但有一个重要细节不同: Python内置cd一般在__new__函数里徏立不变量(invariants)Q从而衍生类不用在调用它的成员函数前调用基类的__init__:

>>> class L(list):
...      def __init__(self):
...          pass
...
>>> L().reverse()
>>>

因ؓC++对象构造是一步操?one-step operation)Q直到参数可用C++实例数据才能被构造,在__init__函数?

>>> class D(SomeBoostPythonClass):
...      def __init__(self):
...          pass
...
>>> D().some_boost_python_method()
Traceback (most recent call last):
  File "<stdin>"Qline 1Qin ?
TypeError: bad argument type for built-in operation

发生错误的原因是Boost.Python 在实例D里找不到cdSomeBoostPythonClass的实例数据;D的__init__函数遮盖了基cȝ构造函数。可以通过删除D的__init__函数或是让它昑ּ的调用SomeBoostPythonClass.__init__(?来纠正错误?/p>

虚函?/a>

在Python里从扩展c衍生新的类型没太大意思,除非它们在C++里能被多态的使用。换句话_当在C++里通过基类指针/引用调用Python成员函数ӞPython成员函数的实现应该看h像是覆盖(override)了C++虚函数的实现。因改变虚函数的行ؓ的唯一Ҏ是在衍生c里覆盖(override)它,用户必须构造一个特D的衍生cL分派(dispatch)多态类的虚函数?

//
// 要包装的接口:
//
class Base
{
 public:
    virtual int f(std::string x) { return 42; }
    virtual ~Base();
};

int calls_f(Base const& bQstd::string x) { return b.f(x); }

//
// 包装代码
//

// 分派者类(Dispatcher class)
struct BaseWrap : Base
{
    // 储存指向Python对象的指?
    BaseWrap(PyObject* self_) : self(self_) {}
    PyObject* self;

    // 当f没有被覆?override)时的~省实现
    int f_default(std::string x) { return this->Base::f(x); }
    // 分派实现
    int f(std::string x) { return call_method<int>(selfQ?f"Qx); }
};

...
    def("calls_f"Qcalls_f);
    class_<BaseQBaseWrap>("Base")
        .def("f"Q?amp;Base::fQ?amp;BaseWrap::f_default)
        ;

下面是一些python演示代码:

>>> class Derived(Base):
...     def f(selfQs):
...          return len(s)
...
>>> calls_f(Base()Q?foo')
42
>>> calls_f(Derived()Q?forty-two')
9

对分z者类(Dispatcher class)Q要注意:

更深层次的反即出?Deeper Reflection on the Horizon)?

无可否认Q重复这U公式化的流E是冗长乏味的。尤其是目里有大量多态类的时候。这反映了C++~译时内省能力的必然限制:无法枚Dcȝ成员来判断哪个是虚函数。不q,一个很有希望的目已经启动Q致力于写一个前端程序来从C++头文件自动生成这些分z者类(以及其它包装代码)?/p>

Pyste 是由Bruno da Silva de Oliveira开发的Q基?GCC_XML 构徏。GCC_XML可以生成XML版本的GCC内部E序描述。GCC是一U高度符?译注QC++标准)的编译器Q从而确保了Ҏ复杂的模板代码的正确处理和对底层cdpȝ的完全访问。和Boost.Python的哲学一_Pyste接口描述既不侵入被包装的代码Q也不用某种不熟悉的语言来表达,相反Q它?00%的纯Python脚本。如果Pyste成功的话Q将标志着我们的很多用户不用再什么都直接用C++包装。它允许我们选择把一些元E序(metaprogram)代码从C++Ud到Python。我们期待不久后不仅用户QBoost.Python开发者自׃能以混合的思\来考虑("thinking hybrid")他们自己的代码?/p>

序列?Serialization)

序列化是把内存中的对象{换成可以保存到磁盘上或通过|络传送的格式的过E。序列化后的对象(最常见的是单字W串)可以被重新取得ƈ转换回原来的对象。好的序列化pȝ能够自动转换整个对象层次(object hierarchies)。Python的标准pickle模块正是q样的系l。它利用语言强大的运行时内省来序列化几乎是Q意的用户定义对象。加上一些简单的非R入限定,q种强大的设施可以被扩展成对被包装的C++对象也有效。下面是一个例?

#include <string>

struct World
{
    World(std::string a_msg) : msg(a_msg) {}
    std::string greet() const { return msg; }
    std::string msg;
};

#include <boost/python.hpp>
using namespace boost::python;

struct World_picklers : pickle_suite
{
  static tuple
  getinitargs(World const& w) { return make_tuple(w.greet()); }
};

BOOST_PYTHON_MODULE(hello)
{
    class_<World>("World"Qinit<std::string>())
        .def("greet"Q?amp;World::greet)
        .def_pickle(World_picklers())
    ;
}

现在让我们创Z个World对象q把它放到磁盘上:

>>> import hello
>>> import pickle
>>> a_world = hello.World("howdy")
>>> pickle.dump(a_worldQopen("my_world"Q?w"))

在可能不同的计算机的可能不同的操作系l的可能不同的脚本中:

>>> import pickle
>>> resurrected_world = pickle.load(open("my_world"Q?r"))
>>> resurrected_world.greet()
'howdy'

当然也可以用cPickle来获得更快的处理速度?/p>

Boost.Python的pickle_suite完全支持标准Python文档定义的pickle协议。类似Python里的__getinitargs__函数Qpickle_suite的getinitargs()负责创徏参数tuple来重pickle了的对象。Python pickle协议中的其他元素Q__getstate__ 和__setstate__可以通过C++ getstate和setstate函数来可选的提供。C++的静态类型系l允许库在编译时保没有意义的函数组?例如Q没有setstate getstate)不会被用?/p>

要想序列化更复杂的C++对象需要做比上面的例子E微多点的工作。幸q的是Object接口(参见下一?在保持代码便于管理上帮了大忙?/p>

对象接口(Object interface)

无所不在的PyObject*Q手动引用计敎ͼ需要记住是哪个API调用q回?新的"(自n拥有?引用或是"借来?(原始?引用Q这些可能有l验的C语言扩展模块的作者都熟悉。这些约束不仅麻烦,更是错误的主要来源,其是存在异常的时候?/p>

Boost.Python提供了一个objectc,它自动化了引用计数ƈ提供Lcd的C++对象到Python的{换。这极大的减M未来的扩展模块作者的学习负担?/p>

从Q一cd创徏object极度?

object s("helloQworld");   // s 理一个Python字符?

object可以和所有其它类型进行模板化的交互,自动的进行到Python的{换。这一切自然得很容易被忽略不计:

object ten_Os = 10 * s[4]; // -> "oooooooooo"

上面的例子中Q在索引和乘法操作被调用前,4?0被{换成了Python对象?/p>

extract<T>cL板可以用来把Python对对象{换成C++cd:

double x = extract<double>(o);

如果M方向的{换不能执行,在q行时抛Z个适当的异常?/p>

伴随objectcd的是一套衍生类型,可能的映射Python的内|类?listQdictQtuple{?。这样就能方便的从C++操作q些高cd?

dict d;
d["some"] = "thing";
d["lucky_number"] = 13;
list l = d.keys();

q看h和工作v来几乎就像是通常的python代码Q但它实际上是纯的C++。当然我们能包装接受或返回object实例的函数?/p>

从؜合的思\思?Thinking hybrid)

因ؓl合~程语言h实际的和心理的困难,在进行Q何实际开发前军_使用单一的语a是普遍现象。对很多应用来说Q性能上的考虑军_了核心算法要用编译语a实现。不q的是,因ؓ静态类型系l的复杂性,我们行时性能要付出开发时间大量增长的代h。经验表明,和开发相应的Python代码比v来,开发可l护的C++代码通常需要更长的旉和艰隑־多才能获得的工作l验。即使开发者觉得只用一门编译语a开发挺好,Z用户Q他们也l常用某U类型的特别的脚本层来补充系l,哪怕他们永q不会得到同L好处?/p>

Boost.Python让我们能 think hybrid 。Python可以用来快速搭建新的应用的原型Q在开发能工作的系l时Q它的易用性和大量的标准库使我们处于领先。需要的话,可以用能工作的代码来扑և限制速度的热?rate-limiting hotspots)。ؓ了最大化性能Q这些热点可以用C++来重新实玎ͼ然后用Boost.Pythonl定来连q已有的高q程(译注Q指PythonE序)?/p>

当然Q如果一开始就清楚很多法最后不得不用C++来实玎ͼq种 由顶至下(top-down) 的方法就没那么吸引h了。幸q的是,Boost.Python也允许我们?由底至上(bottom-up) 的方法。我们非常成功的把这U方法用在了一个用于科学应用的工具pY件的开发上。这个工L开始主要是一个带Boost.Pythonl定的C++cdQ接下来有一段旉增长主要集中在C++部分Q随着工具变得越来越完整Q越来越多新d的功能可以用Python来实现?/p>

http://static.flickr.com/55/124987534_34375196e6.jpg?v=0

上图是实现新的算法时新添加的C++代码和Python代码的估计比率随旉变化的情c我们预计这个比率会辑ֈ接近70% (Python)。能够主要用Python而不是更困难的静态类型语a来解x问题Q这是我们在Boost.Python上的投入的回报。我们的所有代码都能从Python讉KQ这使得更广泛的开发者可以用它来快速开发新的应用?/p>

开发历?/a>

Boost.Python的第一版是由Dave Abrahams在Dragon Systems开发的。在那里他非常荣q的请到Tim Peters作ؓ他的"Python之禅"( "The Zen of Python")导师。Dave的工作之一是开发基于Python的自然语a处理pȝ。因为最l要被用于嵌入式gQ系l计密集的内核L被假设成要用C++来重写以优化速度和内存需求量(memory footprint) [1] 。这个项目也想用Python试脚本 [2] 来测试所有的C++代码。当时我们知道的l定C++和Python的唯一工具?SWIG Q但那时它处理C++的能力比较弱。要说在那时对Boost.Python所使用Ҏ的可能优之处有了什么深L见,那是骗h的。Dave对花俏的C++模板技巧的兴趣和娴熟刚好到了能真正做点什么的时候,Boost.Python那样出CQ因为它满了需求,因ؓ它看h挺酷Q值得一试?/p>

早期的版本针对的许多基本目标和在q篇论文中描q的相同。最显著的区别在于早期版本的语法要稍微麻烦一点,~ZҎ作符重蝲QpicklingQ基于组件的开发的专门支持。后面三个特性很快就被Ullrich Koethe和Ralf Grosse-Kunstleve [3] 加上了。其他热心的贡献?contributors)也出来A献了一些改q,如对嵌套模块和成员函数的支持{?/p>

?001q早期时开发已l稳定下来了Q很有新的Ҏ添加,然而这时一个烦人的问题暴露出来了:Ralf已经开始在一个?EDG 前端的编译器的预发布版上试Boost.PythonQ这时Boost.Python内核中负责处理Python和C++的类型{换的机制(mechanism)~译p|了。结果证明我们一直在利用一个bugQ这个bug在所有我们测试过的C++~译器实C都非常普遍。我们知道随着C++~译器很快变得更加标准兼容,库将开始在更多的^Cp|。很不幸Q因套机制是库的功能的中枢,解决问题看v来非常困难?/p>

q运的是那一q的后期QLawrence Berkeley和后来的Lawrence Livermore National labs?Boost Consulting {订了支持Boost.Python的开发的合同。这样就有了新的Z来处理库的基本问题,从而确保将来的发展。重新设计开始于低cd转换架构Q内|的标准兼容和对Zlg的开发的支持(和不得不昑ּ的跨模块边界导入或导出转换的第一版Ş成对?。对Python和C++对象的关p进行了分析Q从而能更直观的处理C++ lvalues和rvalues?/p>

Python 2.2里出现的强大的新cdpȝ使得选择是否l护对Python 1.5.2的兼Ҏ变得容易了Q这个丢弃大量精心制作的仅仅用来模拟classic Pythoncȝ代码的机会,好的令h无法拒绝。另外,Python iterators ?descriptors提供了重要且优雅的工h描述cM的C++l构。一般化了的对象接口的开发允许我们进一步把C++E序员和使用Python C API带来的危险性和语法负担隔离开。大量的其他Ҏ在q个阶段被加了进来,包括C++异常译Q改q的重蝲函数支持Q还有最重要的用来处理指针和引用的CallPolicies?/p>

?002q十月,W二版的Boost.Python发布了。那以后的开发集中在改进对C++q行时多态和指针的支持上。特别是Peter Dimov的y妙的boost::shared_ptr设计使我们能l؜和系l开发者提供一致的接口Q用于跨语a藩篱来回Ud对象而不丢失信息?/p>

刚开始,我们担心Boost.Python v2的复杂性会ȝ贡献者,?Pyste 和几个其他重要特性的贡献(contribution)的出Cɘq些担心昑־多余了。每天出现在Python C++-sig上的问题和希望得到的改进的积?backlog)表明了库正在被用。对我们来说Q未来看h很光明?/p>

l论

Boost.Python 实现了两U功能丰富的优秀的语a环境间的无缝协作。因为它利用模板元编E技术来对类型和函数q行内省Q用hq用不着再学W三U语a:接口定义是用z而可l护的C++写的。同P包装pȝ不用再解析C++头文件或是描q类型系l:~译器都l我们做了?/p>

计算密集的Q务适合强大的C++Q它一般不可能用纯Python来实现。然而像序列化这L工作Q可能用Python很简单,用C++非常困难。假如有从底层开始构建؜合系l的奢侈Q我们有新的信心和动力来q行设计?/p>



Squirrel 2006-05-15 15:44 发表评论
]]>
Pythonwin VS Eclipse PyDevhttp://www.shnenglu.com/Squirrel/archive/2006/05/15/7187.htmlSquirrelSquirrelMon, 15 May 2006 07:17:00 GMThttp://www.shnenglu.com/Squirrel/archive/2006/05/15/7187.htmlhttp://www.shnenglu.com/Squirrel/comments/7187.htmlhttp://www.shnenglu.com/Squirrel/archive/2006/05/15/7187.html#Feedback0http://www.shnenglu.com/Squirrel/comments/commentRss/7187.htmlhttp://www.shnenglu.com/Squirrel/services/trackbacks/7187.html   同样作ؓIDEQPythonwin ?IDLE 有不o人兴奋的地方Q我开始用Pythonwin也正是由于它的DEBUG环境和别人的推荐。可当我调试Ӟ比如Q一个程序按两次F5Q就出现“Pythonwin.exe 遇到问题需要关闭”,接着是Runtime Error和内存不能ؓ诅R然后必重启Pythonwin才能用!遇到q样的问题,恐怕大多用L心理都难以承受?br />   我后来想起了Eclipse+CDTQ那么有Eclipse+PDT么?果然Q看到网上有Eclipse+PyDev?br />   在Eclipse中选择菜单Q?/font>Help—Software Updates—Find And Install Q选择 Search for new features to intallQ点 New Remote Site 按钮Q输?http://pydev.sf.net/updatesQ?/font>下蝲q安装?br />   配置旉要制定Python解释器,选择正确的\径即可?br />   然后可以在Eclipse下开发调试PythonE序了?br />pyDev.JPG
   
   我也下过BOAQ但感觉现在它还有不缺P毕竟才是alpha版。估计等?.0出来很了?br />   WingIDE 不知道怎么P下次试吧?/font>


Squirrel 2006-05-15 15:17 发表评论
]]>
avԾþþþa鶹| Ʒþþþþ| Ʒþþþþ| 99þۺϹƷ| av˾þۺɫ | ݺݾƷþþĻ | þۺƵվ| þþþþþAv| 99ھƷþþþþþ| Ʒ˾þþ| 99ȾƷþֻоƷ| þþƷ99þþùŴ| 99þþþƷ| ƷëٸAVѾþ| ƷһþþƷ| ղþǿѵĿ| һɫþ88ձȡۺ| þŮcc98cm| ƷŮٸaѾþ| þĻƷѩ| ˾þ| ޹Ʒþþþ| þһ| þۺ¶þü| 99þ99þþƷ| ŷҹƷþþþ| AŮAVۺϾþþ| þþžоƷ23ٻӰԺ| 99þҹɫƷվ| ޹ۺϾþ| ݺɫۺϾþȥ| Ʒһþò| þۺ༤| ڸþþþþ| 97þþþ| þþþavӰ | ˾þô߽avӰԺ | ŷһþþƷ| vaþþþ| רþ| þþƷ|