• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 79  文章 - 58  trackbacks - 0
            <2007年6月>
            272829303112
            3456789
            10111213141516
            17181920212223
            24252627282930
            1234567

            常用鏈接

            留言簿(9)

            隨筆分類

            隨筆檔案

            文章檔案

            相冊

            搜索

            •  

            積分與排名

            • 積分 - 295382
            • 排名 - 87

            最新評論

            閱讀排行榜

            評論排行榜

            pycxx是使用C++語言給python寫擴展代碼的輔助庫,他不像boost.python或者swig那樣封裝的很厚,

            只是對python API的簡單封裝,將python的C API組織成類的形式。

            首先來看pycxx自帶模塊擴展樣例:

            class example_module : public ExtensionModule<example_module>

            {

            public:

                example_module()

                : ExtensionModule<example_module>( "example" )

                {

                    add_varargs_method("sum", &example_module::ex_sum, 

            "sum(arglist) = sum of arguments");

                    add_varargs_method("test", &example_module::ex_test, 

            "test(arglist) runs a test suite");

                    initialize( "documentation for the example module" );

                }

                virtual ~example_module() {}

            private:

                Object ex_sum(const Tuple &a) { ... }

                Object ex_test(const Tuple &a) { ... }

            };

            創建擴展模塊的步驟如下:

            1、從 template<class T> ExtensionModule模板類繼承,class T 實例為本類

            2、構造函數傳入模塊名 ExtensionModule<example_module>( "example" )

            3、實現擴展函數,如實現了

               Object ex_sum(const Tuple &a) { ... }

            4、在構造函數中加入擴展函數

               add_varargs_method("sum", &example_module::ex_sum, 

            "sum(arglist) = sum of arguments");

            5、將擴展模塊注冊到python中

               initialize( "documentation for the example module" );

            6、將模塊對象實例化,模塊屬于單一對象,給出的樣例是:

            void initexample()

            {

                static example_module* example = new example_module;

            }

             

            將擴展模塊注冊到python中靠這個initialize函數

            void initialize( const char *module_doc="" )

            {

                //調用了基類的方法

                ExtensionModuleBase::initialize( module_doc );

                //....

            }

            //最終也就是調用了python的API注冊進去了

            void ExtensionModuleBase::initialize( const char *module_doc )

            {

                PyObject *module_ptr = new ExtensionModuleBasePtr( this );

                Py_InitModule4

                (

                const_cast<char *>( m_module_name.c_str() ),    // name

                m_method_table.table(),                         // methods

                const_cast<char *>( module_doc ),               // docs

                module_ptr,                                     // pass to functions as "self"

                PYTHON_API_VERSION                              // API version

                );

            }

             

            可以看到注冊的時候傳入了m_method_table,是否這個加入擴展函數的地方呢, 這里雖然可以加入,但實際上add_varargs_method

            是加入到method_map_t,相當于該類的靜態成員中。

                    static void add_varargs_method( const char *name, method_varargs_function_t function, const char *doc="" )

                    {

                        method_map_t &mm = methods();

                        mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_varargs_call_handler, doc );

                    }

            method_varargs_function_t是類的成員函數指針,原型如下,這也是pycxx用模板的主要原因了。

            typedef Object (T::*method_varargs_function_t)( const Tuple &args );

             

            在initialize函數里,遍歷了method_map_t,加入到模板的dict中。

                    void initialize( const char *module_doc="" )
                    {
                        ExtensionModuleBase::initialize( module_doc );
                        Dict dict( moduleDictionary() );

                        //
                        // put each of the methods into the modules dictionary
                        // so that we get called back at the function in T.
                        //
                        method_map_t &mm = methods();
                        EXPLICIT_TYPENAME method_map_t::const_iterator i = mm.begin();
                        EXPLICIT_TYPENAME method_map_t::const_iterator i_end = mm.end();
                        for ( ; i != i_end; ++i )
                        {
                            MethodDefExt<T> *method_def = (*i).second;

                            static PyObject *self = PyCObject_FromVoidPtr( this, do_not_dealloc );

                            Tuple args( 2 );
                            args[0] = Object( self );
                            args[1] = Object( PyCObject_FromVoidPtr( method_def, do_not_dealloc ) );

                            PyObject *func = PyCFunction_New
                                                (
                                                &method_def->ext_meth_def,
                                                new_reference_to( args )
                                                );

                            method_def->py_method = Object( func, true );

                            dict[ (*i).first ] = method_def->py_method;
                        }
                    }

             

            真正注冊到python中的函數其實是method_varargs_call_handler,即下面的method_def->ext_meth_def

                            Tuple args( 2 );
                            args[0] = Object( self );
                            args[1] = Object( PyCObject_FromVoidPtr( method_def, do_not_dealloc ) );

                            PyObject *func = PyCFunction_New
                                                (
                                                &method_def->ext_meth_def,
                                                new_reference_to( args )
                                                );

             

            method_varargs_call_handler函數實現如下,第一個參數_self_and_name_tuple就是上面的args,

            args[0]是this指針,args[1]保存著MethodDefExt,里面有成員指向所調用的函數

            extern "C" PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args )
            {
                try
                {
                    Tuple self_and_name_tuple( _self_and_name_tuple );

                    PyObject *self_in_cobject = self_and_name_tuple[0].ptr();
                    void *self_as_void = PyCObject_AsVoidPtr( self_in_cobject );
                    if( self_as_void == NULL )
                        return NULL;

                    ExtensionModuleBase *self = static_cast<ExtensionModuleBase *>( self_as_void );
                    Tuple args( _args );

                    Object result
                            (
                            self->invoke_method_varargs
                                (
                                PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ),
                                args
                                )
                            );

                    return new_reference_to( result.ptr() );
                }
                catch( Exception & )
                {
                    return 0;
                }
            }

            上述實現里又調用invoke_method_varargs,實現如下,這里ext_varargs_function就是真正調用的函數了,如注冊的ex_sum

                    virtual Object invoke_method_varargs( void *method_def, const Tuple &args )
                    {
                        // cast up to the derived class, method_def and call
                        T *self = static_cast<T *>( this );
                        MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( method_def );

                        return (self->*meth_def->ext_varargs_function)( args );
                    }

             

            posted on 2012-03-01 20:59 merlinfang 閱讀(2907) 評論(2)  編輯 收藏 引用 所屬分類: pycxx

            FeedBack:
            # re: pycxx 源碼分析-- 創建python擴展模塊(1) 2012-03-01 23:48 dos命令大全
            表示對py一竅不通  回復  更多評論
              
            # re: pycxx 源碼分析-- 創建python擴展模塊(1) 2012-03-02 09:00 tb
            分析得不錯  回復  更多評論
              
            国产福利电影一区二区三区久久久久成人精品综合 | 久久中文娱乐网| 久久精品人人做人人妻人人玩| 国内精品久久久久久久coent| 欧美午夜A∨大片久久| 亚洲va久久久噜噜噜久久| 久久99国产亚洲高清观看首页| 久久久久久A亚洲欧洲AV冫| 久久精品国产2020| 国产精品va久久久久久久| 久久精品中文无码资源站| 久久亚洲欧美日本精品| 久久久噜噜噜久久中文字幕色伊伊| 久久精品国产亚洲AV无码娇色| 国产免费福利体检区久久| 伊人久久大香线蕉亚洲五月天| 久久国产成人精品国产成人亚洲| 亚洲精品乱码久久久久久中文字幕| 精品久久久久久无码人妻蜜桃| 久久精品亚洲中文字幕无码麻豆| 久久精品国产亚洲AV不卡| 国产精品久久成人影院| 亚洲第一极品精品无码久久| 2021国产成人精品久久| 久久精品亚洲精品国产色婷| 精品久久久一二三区| 久久亚洲天堂| 国产精品免费久久久久电影网| 国产精品美女久久久久久2018| 久久99精品国产麻豆宅宅| 伊人久久五月天| 亚洲午夜福利精品久久| 日韩亚洲国产综合久久久| 久久av高潮av无码av喷吹| 久久www免费人成看国产片| 久久精品无码一区二区三区日韩| 久久精品无码一区二区三区| 久久精品国产99国产精偷| 久久久精品免费国产四虎| 99久久精品国产一区二区蜜芽| 国产高潮国产高潮久久久91|