• <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>

            飯中淹的避難所~~~~~

            偶爾來避難的地方~

              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
              94 隨筆 :: 0 文章 :: 257 評論 :: 0 Trackbacks
            項(xiàng)目里需要使用腳本,我是框架的維護(hù)人員,就需要把腳本系統(tǒng)加入到框架里。
            因?yàn)閷YTHON比較熟悉,所以最后選擇了PYTHON作為腳本系統(tǒng)的主引擎。
            下面是在這個(gè)過程中遇到的種種問題以及最后的解決方法。

            1- 編譯出錯(cuò),提示找不到 __imp_Py_XXXX的引用
               這個(gè)問題真的很惡心,WIN版的PYTHON27.DLL用的是單線DLL的CRT,而項(xiàng)目如果用的是多線LIB的CRT,或者其他不兼容的CRT,就會出這個(gè)問題。
               果斷下載PYTHON2.7.2的源代碼,編譯之。然而,編譯過程也非常的惡心,工程屬性修改成MTd和MT仍舊不行。
               后看到編譯時(shí)有調(diào)用cl的命令行,找了半天在make_buildinfo這個(gè)項(xiàng)目里發(fā)現(xiàn)是使用代碼生成的編譯參數(shù),里面寫死的是MDd,修改之再編譯,問題解決。

            2- Py_Initialize 退出,提示無法找到site模塊。
                這個(gè)問題原本想暴力的修改源代碼里的nosite標(biāo)記改之,后思考可能這個(gè)模塊是有用的,所以把運(yùn)行過PYTHON.EXE的PYTHON運(yùn)行路徑里的LIB里的被編譯成PYC的所有PY按路徑復(fù)制到EXE的路徑下,問題解決。

            3- 不想用BOOST.PYTHON,又想不用寫PyCFunction的形式的C模塊方法
                這個(gè)問題經(jīng)過分析,得到結(jié)論是,從任意形式的用戶函數(shù)生成一個(gè)PyObject*(*PYFUNC)(PyObject*,PyObject*)形式的函數(shù)封裝。并且對于一個(gè)獨(dú)立地址的用戶函數(shù),需要一個(gè)獨(dú)立地址的函數(shù)封裝。
                首先,我開始解決如何從一個(gè)固定函數(shù)得到另一個(gè)固定地址函數(shù)。一開始我想到用函數(shù)地址作為模版參數(shù),這樣每個(gè)獨(dú)立地址就能生成一個(gè)單獨(dú)的模版類,然后模版類里的靜態(tài)函數(shù)自然就是獨(dú)立地址的。后我使用了static的本地函數(shù)測試,未果,提示什么non-extra的錯(cuò)誤。后進(jìn)群詢問,得到同樣答案,并且編譯成功的結(jié)果。仔細(xì)觀察后發(fā)現(xiàn),他用的是非static修飾的函數(shù)。我去掉static修飾,竟然成了。
                接下來,我開始解決如何從PyObject*args解析出用戶函數(shù)的每個(gè)參數(shù)的問題。這個(gè)問題有幾個(gè)部分,第一部分是如何從函數(shù)里析出每個(gè)參數(shù),這部分我用了模版的某種特化,具體名字我不懂,就是如下面這種形式:
               
            template <typename TR, typename T1 = void, typename T2 = void>
            struct st_func {};
            template 
            <typename TR, typename T1>
            struct st_func<TR, T1, void> {};

                這樣就可以析出返回值TR和各個(gè)參數(shù)的類型。為了支持盡可能多的參數(shù),我寫了個(gè)程序生成了從0個(gè)參數(shù)到40個(gè)參數(shù)的模版變體。
                使用固定地址,因?yàn)楹瘮?shù)定義需要TR,T1,所以函數(shù)指針無法直接在第一個(gè)模版參數(shù)傳遞,并且是固定參數(shù),無法放在可選參數(shù)后面,所以我選擇了先在第一個(gè)參數(shù)用void*傳遞函數(shù)指針,然后在st_func內(nèi)部用TR,T1...這些拼出一個(gè)函數(shù)指針,把首位置的指針強(qiáng)轉(zhuǎn)成原函數(shù)形式,再進(jìn)行調(diào)用。
                因?yàn)镻YTHON的解析函數(shù)需要每個(gè)參數(shù)的類型標(biāo)識符,大部分類型是一個(gè)字符表示,這部分用了enum來為每個(gè)類型生成一個(gè)const且static的字符標(biāo)識。比如
            template <> struct type_char<int> { enum{ typechar = 'i' };};
                然后最終PyArg_ParseTuple 需要的是一個(gè)字符串,那么我在代碼里就 這樣來生成這個(gè)字符串:
               
            char szTypes[] = { type_char<T1>::typechar, .., 0 };
                最后一個(gè)部分是解決TR是void時(shí)的函數(shù)返回值問題。后來我用了struct內(nèi)部的特化函數(shù)來解決。最終形式如下:


            template <void* FP, typename TR, typename T1>
            struct st_cppfunc_to_py<FP, TR, T1, void, void>
            {
            typedef TR (
            *TFP)(T1);
            static PyObject * func( PyObject * self, PyObject * args ) { return _func<TR>( self, args ); }
            template
            <typename ITR>
            static PyObject * _func( PyObject * self, PyObject * args ) {
            char szType[] = { type_char<T1>::typechar, 0 };
            T1 v1;
            if( PyArg_ParseTuple( args, szType, &v1 ) ) {
            TR ret
            = ((TFP)FP)( v1 );
            char szRetType[2] = { type_char<TR>::typechar, 0 };
            return Py_BuildValue( szRetType, ret );
            }
            Py_RETURN_NONE;
            }
            template
            <>
            static PyObject * _func<void>( PyObject * self, PyObject * args ) {
            char szType[] = { type_char<T1>::typechar, 0 };
            T1 v1;
            if( PyArg_ParseTuple( args, szType, &v1 ) ) {
            ((TFP)FP)( v1 );
            }
            Py_RETURN_NONE;
            }

            };

            外面包一個(gè)  template <void*FP, typename TR, typename T1> PyCFunction __cppfunc2py( TR(*RFP)(T1) ) { return st_cppfunc_to_py<FP, TR, T1>::func; }

            就可以很方便的生成嵌入PY的函數(shù)了。

            4- 包裝的scriptvalue怎么獲得PyObject*的類型呢
                用Py_TYPE(ob)就可以獲取到object的typeobject,它的tp_name就是它的名字,常用類型 int, long, float, str 都可以分辨出來。

            5- PYTHON的調(diào)試版總是報(bào)GC異常
                這個(gè)問題我是嘗試著來解決的,總結(jié)了以下幾點(diǎn):
                a. 模塊的DICT是不用PY_XDECREF來釋放的   
                b. 返回值需要一個(gè)PY_XDECREF釋放。
                c. Py_BuildValue 返回值需要一個(gè)PY_XDECREF。
                d. 用戶模塊不需要 PY_XDECREF。
                e. PY文件生成的模塊需要一個(gè) PY_XDECREF。
                f. Set Object到Tuple去調(diào)完P(guān)Y的函數(shù),PY_XDECREF(TUPLE)時(shí),需要注意的是,Set進(jìn)去的Object都會被調(diào)用一次Py_XDECREF,所以一個(gè)好的辦法是在Set進(jìn)Tuple時(shí),就INC一下他們的REF。
            6- 為何一直調(diào)不到py文件里的函數(shù)
                這個(gè)問題困擾了我?guī)追昼姡K的method獲取不到,讓我一度以為是腳本寫的問題。
                后來我打印出來腳本的搜索路徑(print sys.path),是一大堆的路徑,我放進(jìn)去的路徑排在最后。于是我想,是不是有的路徑下有重名的PY文件,就給文件改了個(gè)名字,結(jié)果就OK了。
                這個(gè)問題,我后來想可以通過調(diào)整搜索優(yōu)先級來解決,不過目前還是這樣解決比較好,因?yàn)檎{(diào)整方法目前還不得而知。

               
            posted on 2012-02-10 21:55 飯中淹 閱讀(3264) 評論(0)  編輯 收藏 引用

            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            精品久久久久久亚洲精品| 久久人人爽人人爽人人AV| 久久九九亚洲精品| 国产巨作麻豆欧美亚洲综合久久 | 久久久久久久亚洲Av无码| 久久精品国产亚洲AV蜜臀色欲| 亚洲av伊人久久综合密臀性色| 久久精品国产亚洲av影院| 久久精品18| 久久精品国产亚洲av影院| 久久久久久一区国产精品| 一本色道久久HEZYO无码| 丰满少妇人妻久久久久久4| 波多野结衣久久| 99久久国产综合精品五月天喷水| 大香伊人久久精品一区二区| 国产午夜久久影院| 中文无码久久精品| 久久这里只有精品视频99| 久久久久无码精品国产不卡| 日韩精品无码久久一区二区三| 99久久精品国产免看国产一区| 少妇久久久久久被弄到高潮| 欧美精品一本久久男人的天堂| 亚洲va久久久噜噜噜久久男同| 性做久久久久久免费观看| www亚洲欲色成人久久精品| 国内精品伊人久久久久| 色婷婷综合久久久中文字幕| 精品综合久久久久久97| 婷婷久久五月天| 久久久久人妻精品一区三寸蜜桃| 久久线看观看精品香蕉国产| av无码久久久久不卡免费网站| 亚洲熟妇无码另类久久久| 久久AV高潮AV无码AV| 精品伊人久久大线蕉色首页| 97精品伊人久久大香线蕉| 人妻精品久久久久中文字幕 | 中文字幕精品久久久久人妻| 久久伊人精品青青草原日本|