• <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>
            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            統(tǒng)計

            • 隨筆 - 44
            • 文章 - 0
            • 評論 - 86
            • 引用 - 0

            常用鏈接

            留言簿(6)

            隨筆分類(31)

            隨筆檔案(44)

            Mining

            最新隨筆

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            2009年2月17日

            Google 是下一個受害者嗎?


            John Borthwick 在 Google Next Victim Of Creative Destruction? 一文中闡述了AOL 的死亡以及產(chǎn)業(yè)的不斷循環(huán), yahoo, ebay 等已經(jīng)成為技術(shù)革新的受害者.

            隨著搜索的垂直分割, 搜索市場也被細(xì)化
            1. 視頻搜索的突起, youtube 從2007.10 到 2008.10 的搜索增長了114%, 占了google 搜索的26%.
             2. 實時消息的發(fā)展, 以twitter 為代表, 市場對突發(fā)事件的要求的強烈, 使得twitter 迅速發(fā)展, twitter 的搜索(http://search.twitter.com/)與傳統(tǒng)引擎依賴內(nèi)容相關(guān)以及鏈接關(guān)系相比, 更注重時間的相關(guān)性.

            Gerry campbell 的文章 Search is broken – really broken. 的一個圖說明了這種趨勢



            posted @ 2009-02-17 14:57 泡泡牛 閱讀(1426) | 評論 (1)編輯 收藏

            2008年12月19日

            Pythong logging 到 Logging4cplus 的適配器

            Python 的logging 模塊的Socket 和 Logging4cplus 的 socket 的格式是不一樣的, 現(xiàn)實中需要將日志發(fā)送到logging4cplus 的服務(wù)器, 不得已, 寫了個 Python logging 模塊到 logging4cplus的Adapter

             1 #!/usr/bin/env python
             2 #-*- coding: gbk -*-
             3 from struct import pack, unpack 
             4 
             5 class BufferPack(object):    
             6     def __init__(self):
             7         self.buffer = ''
             8         
             9     def addChar(self, s, unsigned=False):
            10         self.buffer += pack(unsigned and '>b' or '>c', s )
            11 
            12     def addShort(self, s, unsigned=False):
            13         self.buffer += pack(unsigned and '>H' or '>h', s )
            14     
            15     def addInt(self, s, unsigned=False):
            16         self.buffer += pack(unsigned and '>I' or '>i', s )
            17     
            18     def addLong(self, s, unsigned=False):
            19         self.buffer += pack(unsigned and '>L' or '>l', s )
            20     
            21     def addString(self, s):
            22         self.addInt( len(s) ) 
            23         self.buffer += s 
            24     
            25     def addBuffer(self, s):
            26         self.buffer += s.buffer 
            27 
            28 class BufferUnpack(object):
            29     
            30     char_bits     = len( pack('>b', 0) ) 
            31     short_bits     = len( pack('>H', 0) ) 
            32     int_bits    = len( pack('>I', 0) ) 
            33     long_bits     = len( pack('>L', 0) )    
            34     
            35     def __init__(self, buffer):
            36         self.buffer = buffer 
            37         self.pos = 0
            38     
            39     def _read_item(self, unpackstr, len):
            40         v = unpack(unpackstr, self.buffer[self.pos:self.pos+len] )
            41         self.pos += len 
            42         return v 
            43     
            44     def readChar(self, unsigned=False):
            45         return self._read_item(unsigned and '<b' or '<c', self.char_bits)
            46     
            47     def readShort(self, unsigned=False):    
            48         return self._read_item(unsigned and '<H' or '<h', self.short_bits )
            49         
            50     def readInt(self, unsigned=False):
            51         return self._read_item(unsigned and '<I' or '<i', self.int_bits )
            52     
            53     def readLong(self, unsigned=False):
            54         return self._read_item(unsigned and '<L' or '<l', self.long_bits )
            55     
            56     def readString(self):
            57         len = self.readInt()
            58         v = self.buffer[self.pos:self.pos+len] 
            59         self.pos += len
            60         return v 
            61 
            62 def PackMessage( record ):
            63     bp = BufferPack()
            64     bp.addChar(2, True) 
            65     bp.addChar(1, True) 
            66     
            67     bp.addString("{log.servername}"
            68     bp.addString(record.name) 
            69     bp.addInt(record.levelno*1000
            70     bp.addString("")
            71     bp.addString(record.msg)
            72     bp.addString(str(record.threadName))
            73     bp.addString(str(record.process))
            74     bp.addInt( record.created ) 
            75     bp.addInt( record.msecs ) 
            76     bp.addString(record.filename)
            77     bp.addInt( 1 )     
            78     
            79     pkg = BufferPack()
            80     pkg.addInt(len(bp.buffer), True) 
            81     pkg.addBuffer( bp ) 
            82     
            83     return pkg.buffer
            84 
            85 if __name__=="__main__":
            86     import logging, logging.handlers 
            87     
            88     logger = logging.getLogger()
            89     logging.handlers.SocketHandler.makePickle = lambda self,rc : PackMessage(rc) 
            90     
            91     hdlr = logging.handlers.SocketHandler('{logserver.ip}'8888
            92     formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
            93     hdlr.setFormatter(formatter)
            94     logger.addHandler(hdlr)
            95     logger.setLevel(logging.NOTSET)
            96     
            97     logger.info("hello")

            使用的時候.
            1. 在logging 創(chuàng)建SocketHandler 的時候, 需要修改logging.handlers.SocketHandler.makePickle 為方法 PackMessage
            logging.handlers.SocketHandler.makePickle = lambda self,rc : PackMessage(rc)

            2. 需要修改代碼中的兩部分內(nèi)容 {log.servername} 和 {logserver.ip}

            posted @ 2008-12-19 18:13 泡泡牛 閱讀(998) | 評論 (0)編輯 收藏

            2008年12月4日

            BHO基礎(chǔ)

            BHO就是Browser Helper Object(瀏覽器輔助對象)

            BHO關(guān)聯(lián)原理 (BHO關(guān)聯(lián)的是SHDOCVW,也就是說不只關(guān)聯(lián)IE,下面全部用IE來說明)
            1.IE的窗口打開時,先尋找HKLM下的SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects\ 里的CLSID,這些CLSID,都對應(yīng)著相應(yīng)的BHO插件,然后根據(jù)這個CLSID到HKCR下的CLSIDs里找到此插件的信息,包括文件位置等。
            2.IE根據(jù)找到的CLSID信息創(chuàng)建 BHO 對象,并且查找 IObjectWithSite 接口. (這個接口非常簡單,只有SetSite和GetSite兩個方法)
            3.IE把IWebBrowser2(瀏覽器插件)傳到 BHO 的 SetSite 方法,用戶在此方法中可掛載自己的事件處理方法。
            4.窗口關(guān)閉時,IE把 null 傳到 BHO 的 SetSite 方法,此方法用來去掉掛載的事件處理方法。

            編寫B(tài)HO流程
            1.創(chuàng)建IObjectWithSite顯式接口,創(chuàng)建 COM 類型,實現(xiàn)繼承IObjectWithSite接口
            2.實現(xiàn)此接口并在SetSite方法里加上所要掛載的事件
            3.處理事件
            4.注冊此BHO到注冊表中HKLM下的Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects;(HKCR下的CLSIDs是根據(jù)上面的路徑自動注冊的)
            5、.net 下須設(shè)置此BHO項目的 配置屬性_>生成 中為Interop注冊為True,這樣才能將.net 類庫文件注冊到COM

            刪除BHO
            打開注冊表項到:HKLM下的Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects 可以看到下面有一些CLSID值,這些值對應(yīng)相關(guān)的插件,點擊可以在默認(rèn)值后看到相關(guān)插件的名稱!可以復(fù)制相關(guān)CLSID到注冊表中搜索相關(guān)CLSID,找到后打開InprocServer32可以看到相關(guān)文件的路徑,至于DLL文件等可以用UEDIT32.exe工具打開查看具體信息,當(dāng)然也可以用修改程序類的eXeScope.exe研究一下!
            請根據(jù)具體情況刪除相關(guān)鍵值和相關(guān)文件!

            REF:
            BHO 的編寫 
            VCKBase 關(guān)于IE 編程文檔中心
            C++中使用BHO來屏蔽特定網(wǎng)站
            瀏覽器集成教學(xué) 自定義瀏覽器

            posted @ 2008-12-04 17:26 泡泡牛 閱讀(2270) | 評論 (0)編輯 收藏

            2008年10月29日

            36 steps to success as technical lead

            zz http://littletutorials.com/2008/07/07/success-as-technical-lead/ 
            分為3個部分
            Set yourself up for success
            Build your relationship with the team
            Build your relationship with the management and business people

            Set yourself up for success

            1. Define early on what success means for you, the team and the business

            You have to have a clear idea of what you want. You also have to understand what team members and the management want. You also have to be aware that what people really want, what they say the want and sometimes even what they think they want are very different things. Try to be very honest at least with yourself. Success has different definitions for different people. If there is a big disconnect between these definitions you have a problem before you start.

            2. Believe in the project: idea, architecture, time, team

            You cannot have any kind of success if you are convinced you lead a team of morons to implement a stupid idea using the wrong architecture in a ridiculously short time. You have to really believe in the project to have a chance to success. This does not mean lie to yourself. It means do whatever you can to understand your concerns and work on them with the management. As for the architecture, it is best if you have a heavy word or if you are the architect.

            3. Understand the domain, the business requirements and the technical challenges

            You should be an expert in the technologies used for implementation. You also have to become very knowledgeable in the problem domain and the business case. This will help you understand the business decisions dropped on your head from upstairs and also will help you stand a chance at negotiating them.

            4. Know your team: strengths, weaknesses, ambitions and personalities

            Software is created by people. Your job as a “tech lead” is to support them in doing that, both from a technical point of view and at a human level. You want to lead a team of motivated and enthusiastic people. But each person gets motivated by different things.

            5. Have a plan as a result of a planning activity

            “Plans are useless but planning is essential” - (Dwight D Eisenhower, US President, general 1890-1969). Planning will make you think about the problems you face in detail. Also keep in mind that “a plan is just a list of things that ain’t gonna happen” - (Benicio Del Torro in “The Way of the Gun”).

            6. Be part in the design of everything

            This does not mean do the whole design. You want to empower team members. But your job is to understand and influence each significant subsystem in order to maintain architectural integrity.

            7. Get your hands dirty and code

            Yes you should take parts of the code and implement them. Even the least glamorous parts. This will help you not getting stuck alone between management and the team. It will also help you gain respect in the team.

            8. Act as a communication proxy for your team

            In long complex projects with big teams communication is one of the most complicated aspects. The more people you have involved in solving a problem the bigger the communication matrix becomes. Since people need information to be able to make the right decisions this will lead to an exponential increase in the time consumed for communication. Agile methodologies alleviate this problem. But in the end it is up to you to propagate important information to the right people.

            9. Make sure everybody understands the big picture: their work has implications

            This will help you greatly because will allow team members to design and implement in a way that you don’t have to fight. It is also hard work from your part.

            10. Fight for architecture and design consistency

            Doing the right thing from the design and architecture point of view is not more costly. It is actually cheaper in every project longer than a couple of months. Every early investment in architecture pays for itself later during integration and maintenance. Even if you have to admit an occasional hack or prototype in the code base you should contain it in very specific modules.

            11. Know the status of everybody’s work and detect slippage

            This allows for corrective actions and for early communication with the management. You don’t want to be caught by surprise. Remember that during 90% of the allocated time for a task the code is 90% complete.

            12. Record technical debt if you need shortcuts but try to maintain architectural integrity; report the debt

            This one is very important for products that will have multiple releases. Technical debt should be analyzed at the beginning of each iteration.

            13. Use the process that makes sense in your particular case

            Tough one. Sometimes (most of the times?) the process is not up to you. In the enterprise usually the process is pre-decided. But always keep in mind that the process in itself means nothing. It is the people who give meaning to the process. Good people can make the worst process work while the wrong team cannot make any process work. Waterfall can be implemented in a very agile way and the agile methodologies can be applied with “rigor mortis” agility (see The Agile 800 Pounds Gorilla).

            14. Avoid dogmas - question why everything is done the way is done; make sure everybody else knows the reasons

            Sometimes I hear from programmers: we are agile and combine XP and Scrum and we also do TDD (Test Driven Development - I still hope for a TDD that means Thought Driven Development). The questions that pop up in my mind are: Do you need all those? Do you “really” do them by the book?
            Anyway the point here is don’t do anything just because it is the way it has always been done. Understand why. Then explain the reasons to all team members. Rinse and repeat.

            15. Avoid design by committee; listen to everybody but make your own decisions

            No good design is born from referendum. There are lots of people making wild exotic suggestions when their a$$ is not on the line. There are also excessively prudent ideas born from fear. Even with good ideas you have to filter them and make them yours before you can include them in the design. A good architecture and a good design is usually born in one mind, an open mind that looks around. The obvious example is Linux.


            Build your relationship with the team

            16. Gain the team’s respect with the quality of your work and by doing what you are preaching17. Be fair
            18. Admit your mistakes
            19. Publicly recognize both team’s and individual members’ merits
            20. Don’t blame anybody publicly for anything
            21. Build morale and confidence by offering early victories to the team and to its individual members
            22. Match people and tasks based on skills and their personal preference if possible; explain your decisions
            23. Work the estimates with the team don’t come up with them
            24. Mentor people
            25. Listen to and learn from people
            26. Explain your technical decisions

            Build your relationship with the management and business people
            27. Be sure you have authority along with responsibility
            28. Be sure you get requirements and not architecture/design masked as requirements
            29. Explain technical decisions in business terms
            30. Try to be accurate in your estimates; avoid being too optimistic and don’t push it with hidden padding; explain the need for padding
            31. Set reasonable expectations
            32. Understand the relationships and dependencies with other teams or projects
            33. Accurately report the status with alarms, explanations and solutions; report any technical debt
            34. Resist pressure for change in requirements, and more important for shortcuts…
            35. Be aware of politics
            36. React to surprises with calm and with documented answers

            posted @ 2008-10-29 21:45 泡泡牛 閱讀(1079) | 評論 (0)編輯 收藏
            Top 25 PHP template engines

            zz http://www.whenpenguinsattack.com/2006/07/19/php-template-engine-roundup/ 


            該文總結(jié)了 php 的一些模板. 我使用過的有smarty, template lib, 還有后來用的 Savant. 感覺smarty 太復(fù)雜了, template lib 需要學(xué)習(xí)一些標(biāo)簽, 并且不是很強大, 綜合考慮還是Savant 最好, 既可以使用模板機制, 另外頁面模板直接使用php 函數(shù)來輸出. 功能也還可以.

            Smarty
            Smarty is a template engine that compiles the templates into PHP scripts, then executes those scripts. Very fast, very flexible.

            Savant
            A powerful but lightweight PEAR-compliant template system. It is non-compiling, and uses PHP itself as its template language.

            Heyes Template Class

            A very easy to use, yet powerful and quick template engine that enables you to separate your page layout and design from your code.

            FastTemplate
            A simple variable interpolation template class that parses your templates for variables and spits out HTML with their values

            ShellPage
            A simple and easy to use class that lets you make whole websites based on template files for layouts. Change the template and your whole site changes.

            STP Simple Template Parser
            A simple, light weight and easy to use template parser class. It can assemble a page from several templates, output result pages to the browser or write them to the filesystem.

            OO Template Class
            An object oriented template class you can use in your own programs.

            SimpleTemplate
            A template engine to create and structure websites and applications. It can translate and compile the templates.

            bTemplate
            A small and fast template class that allows you to separate your PHP logic from your HTML presentation code.

            ETS - easy template system
            A template system that allows you to reshuffle templates with exactly the same data.

            EasyTemplatePHP
            A simple, yet powerful templating system for your site.

            vlibTemplate
            A fast, full featured template system that includes a caching and debugging class.

            AvanTemplate
            A template engine that is multi-byte safe and consumes little computing resource. It supports variable replacement and content blocks that can be set to hidden or shown.

            Grafx Software’s Fast Template
            A modification of the popular Fast Template system, this includes a cache function, debug console, and silent removal of unassigned dynamic blocks.

            TemplatePower
            A fast, simple and powerful template class. Features nested dynamic block support, block/file include support and show/hide unassigned variables.

            TagTemplate
            This library function was designed for use with template files and allows you to retrieve info from HTML files.

            htmltmpl: templating engine
            A templating engine for Python and PHP. Targeted to web application developers, who want to separate program code and design of their projects.

            PHP Class for Parsing Dreamweaver templates
            A simple class to parse a Dreamweaver template for use in custom mods for a Gallery 2 and a WordPress blog.

            MiniTemplator (Template Engine)
            A compact template engine for HTML files. It features a simple syntax for template variables and blocks. Blocks can be nested.

            Layout Solution
            Simplifies website development and maintenance. It holds commonly used variables and page elements so you don’t need to duplicate common layouts over and over.

            Cached Fast Template
            This inclusion into FastTemplate allows for caching of the template files, and can even cache with different specifications on separate blocks of content.

            TinyButStrong
            A template engine that supports MySQL, Odbc, Sql-Server and ADODB. It includes seven methods and two properties.

            Brian Lozier’s php based template engine
            Only 2k in size, very fast and object-orientated.

            WACT
            a template engine that separates code from design.

            PHPTAL
            a XML/XHTML template library for PHP.

            ref:
            http://www.sitepoint.com/forums/showthread.php?t=123769 對其他的php 模板進(jìn)行了討論

            posted @ 2008-10-29 21:28 泡泡牛 閱讀(1450) | 評論 (1)編輯 收藏

            2008年10月6日

            深入理解Effictive C++ "條款38: 決不要重新定義繼承而來的缺省參數(shù)值"

            看條款38 的時候不是很理解, 于是寫了個測試代碼

            #include<iostream> 
            using namespace std; 

            class A{
            public:
                
            virtual void show(int a=145)
                {
                    cout
            <<"A: a="<<a<<endl; 
                }   
            }; 

            class B: public A 

            public
                
            void show(int b)
                { 
                    cout
            <<"B: b="<<b<<endl; 
                } 
            }; 
            class C: public B 

            public
                
            void show(int c=999)
                { 
                    cout
            <<"C: c="<<c<<endl; 
                } 
            };
            class D: public C 

            public
                
            void show()
                { 
                    cout
            <<"D:\n"
                }
            }; 

            void main() 
            {
                A 
            *pp;
                A a; 
                B b; 
                C c; 
                D d;
                
                a.show();
                pp 
            = &a;    pp->show();

                
            // b.show();  // error C2660: 'B::show' : function does not take 0 arguments
                pp = &b;    pp->show();
                
                c.show();
                pp 
            = &c;    pp->show();

                d.show();
                pp 
            = &d;    pp->show();
                
                C 
            *pc= &d;
                pc
            ->show();

                system(
            "pause"); 
            }   
            輸出結(jié)果是
            A: a=145
            A: a=145
            B: b=145
            C: c=999
            C: c=145
            D:
            C: c=145
            C: c=999

            回顧條款 
            虛函數(shù)是動態(tài)綁定而缺省參數(shù)值是靜態(tài)綁定的.  為什么C++堅持這種有違常規(guī)的做法呢?答案和運行效率有關(guān)。如果缺省參數(shù)值被動態(tài)綁定,編譯器就必須想辦法為虛函數(shù)在運行時確定合適的缺省值,這將比現(xiàn)在采用的在編譯階段確定缺省值的機制更慢更復(fù)雜。做出這種選擇是想求得速度上的提高和實現(xiàn)上的簡便,所以大家現(xiàn)在才能感受得到程序運行的高效;

            所以
            a. 靜態(tài)綁定 .vs. 動態(tài)綁定
            A *pp = new B;
            這里 pp 靜態(tài)綁定是 A* , 而動態(tài)綁定卻是 B*
            B *pb = new B;
            這里 pb 靜態(tài)綁定和動態(tài)綁定是一樣的都是 B*

            b. 缺省值是靜態(tài)綁定的, 而非動態(tài)綁定
            所以
            d.show() 輸出 D:  因為show 被 D override

            pp = &d;    pp->show();  
            pp 被動態(tài)綁定到D *, 但是show 的缺省值卻是A* 的 145, 所以輸出的是 C: c=145, 而不是999 ( 函數(shù) show 被C 給override 了) 

            而 C *pc = &d; pc->show() , pc 靜態(tài)綁定為C*, 而動態(tài)綁定為 D* , 所以輸出的是 C: c=999 , 999 是 C* 靜態(tài)綁定的缺省值

            c. 所以調(diào)用b.show 的時候出現(xiàn)了如下的錯誤
                // b.show();  // error C2660: 'B::show' : function does not take 0 arguments
            因為 B* 沒有靜態(tài)綁定的函數(shù)

            結(jié)論就是 決不要重新定義繼承而來的缺省參數(shù)值 

            ref: 
            從這里學(xué)了不少:) http://bbs.chinaunix.net/viewthread.php?tid=439188 

            posted @ 2008-10-06 17:19 泡泡牛 閱讀(2827) | 評論 (6)編輯 收藏

            2008年10月3日

            Python 操作黑莓(Blackberry)通信錄

            為了給黑莓導(dǎo)入iPhone 的通信錄(contacts) , 只能利用黑莓的桌面管理器, 通過ipd 來維護(hù).
            但是發(fā)現(xiàn) ABC Amber BlackBerry Converter 只能轉(zhuǎn)換而無法修改, IPDManager 只能維護(hù)鈴聲和音樂啥的:(  只能自己寫了個小程序

            ipd 的格式可以在 http://na.blackberry.com/eng/developers/resources/journals/jan_2006/ipd_file_format.jsp 這里找到, 后面是代碼, 只是生成datablock 列表, 還需要額外拷貝. 操作時最好只同步通信錄.

            下面是代碼

            #!/usr/local/bin/python2.5 
            #
            -*- coding: gbk -*-
            from struct import * 

            class BBFile:    
                
            def __init__(self):
                    
            pass
                    
                
            def _contactblock(self, name, phone, uid):
                    s 
            = ''
                    
            # name 
                    name = name.encode("utf-16be")
                    s 
            += pack('<HB', len(name)+10xa0)
                    s 
            += pack('<B'0x01+ name
                    
            # ff * 8 
                    s += pack('<HB'80x54)
                    s 
            += '\xff'*8
                    
            # uid 
                    s += pack('<HBI'40x55, uid)
                    
            # phone
                    phone = phone.encode("gbk")
                    s 
            += pack('<HB', len(phone)+10x08)
                    s 
            += phone + '\x00'
                    
            return s 
                
                
            def save(self, filename, us, dbID=0, dbVer=0):
                    hf 
            = open(filename, "w+b")
                    rs, uid 
            = 1363797835 # 初始值
                    for u in us:
                        s 
            = self._contactblock(u[0], u[1], uid)
                        h 
            = pack('<HIBHI', dbID, len(s)+7, dbVer, rs, uid)
                        hf.write(h 
            + s)
                        uid 
            += 8    # 
                        rs  += 1    # 
                    hf.close()
                    
            if __name__=='__main__':
                bb 
            = BBFile()
                us 
            = [ (u'寶寶1', u'13888888888'),(u'寶寶2', u'13888888888'),(u'寶寶3', u'13888888888'),  ]    
                bb.save(
            "bb.ipd", us, 0, 0)
            1. 保存成文件就可以直接運行了:)
            2. 如果要真的生成可以導(dǎo)入bb 的文件的話, 要使用高級-> 只同步通訊錄, 然后將這個文件生成的內(nèi)容放在導(dǎo)出文件的頭的后面, 還是有點麻煩.... 有空做個全自動的 呵呵   

            因為只是測試, 所以很多硬編碼了:)    

            posted @ 2008-10-03 22:18 泡泡牛 閱讀(3352) | 評論 (6)編輯 收藏

            2008年9月25日

            Http 基礎(chǔ)

            = HTTP 基礎(chǔ)
            一個完整的 HTTP 請求可以分成4步:
             1. 創(chuàng)建TCP socket, 連接到Web 服務(wù)器
             2. 發(fā)送Http 請求頭
             3. 接受Web 響應(yīng)數(shù)據(jù)
             4. 關(guān)閉socket 連接
            整個流程可以通過telnet hostname 80 來模擬
            一個完整的請求例子如下
            * About to connect() to www.baidu.com port 80 (#0)
            *   Trying 202.108.22.5... connected
            * Connected to www.baidu.com (202.108.22.5) port 80 (#0)
            > GET / HTTP/1.1
            > User-Agent: curl/7.16.4 (i586-pc-mingw32msvc) libcurl/7.16.4 OpenSSL/0.9.7e zlib/1.2.2
            > Host: www.baidu.com
            > Accept: */*
            >
            < HTTP/1.1 200 OK
            < Date: Thu, 25 Sep 2008 05:14:30 GMT
            < Server: BWS/1.0
            < Content-Length: 3342
            < Content-Type: text/html
            < Cache-Control: private
            < Expires: Thu, 25 Sep 2008 05:14:30 GMT
            < Set-Cookie: BAIDUID=3A8165EF68FFEE5F605D33ADEF300BA1:FG=1; expires=Thu, 25-Sep-38 05:14:30 GMT; path=/; domain=.baidu.com
            < P3P: CP=" OTI DSP COR IVA OUR IND COM "
            <
            <html><head><meta http-equiv=Content-Type content="text/html;charset=gb2312"><title>......

            另外值得說明的是, HTTP 請求是無狀態(tài)的,表明在處理一個請求時,Web服務(wù)器并不記住來自同一客戶端的請求。

            = Http 請求頭
            包含4個部分: 請求行、請求頭、空行和請求數(shù)據(jù)

            1. 請求行
            由三個標(biāo)記組成:請求方法、請求URI和HTTP版本,它們用空格分隔, 如:GET /index.html HTTP/1.1

            HTTP 規(guī)范定義了8種請求方法:
            GET   檢索URI中標(biāo)識資源的一個簡單請求
            HEAD   與GET方法相同,服務(wù)器只返回狀態(tài)行和頭標(biāo),并不返回請求文檔
            POST   服務(wù)器接受被寫入客戶端輸出流中的數(shù)據(jù)的請求
            PUT   服務(wù)器保存請求數(shù)據(jù)作為指定URI新內(nèi)容的請求
            DELETE   服務(wù)器刪除URI中命名的資源的請求
            OPTIONS  關(guān)于服務(wù)器支持的請求方法信息的請求
            TRACE   Web服務(wù)器反饋Http請求和其頭標(biāo)的請求
            CONNECT  已文檔化但當(dāng)前未實現(xiàn)的一個方法,預(yù)留做隧道處理

            2. 請求頭 [ 可無 ]
            由關(guān)鍵字及值對組成,每行一對,關(guān)鍵字和值用冒號(:)分隔。如
            > User-Agent: curl/7.16.4 (i586-pc-mingw32msvc) libcurl/7.16.4 OpenSSL/0.9.7e zlib/1.2.2
            > Host: www.baidu.com
            > Accept: */*
            具體請求頭如后所列

            3. 空行
            最后一個請求頭之后是一個空行,發(fā)送回車符和退行,通知服務(wù)器以下不再有頭標(biāo)。

            4. 請求數(shù)據(jù) [ 可無 ]
            使用POST傳送數(shù)據(jù),最常使用的是Content-Type和Content-Length頭標(biāo)


            = Web 響應(yīng)
            由四個部分組成: 狀態(tài)行、響應(yīng)頭、空行、響應(yīng)數(shù)據(jù), 如:
            < HTTP/1.1 200 OK
            < Date: Thu, 25 Sep 2008 05:14:30 GMT
            < Server: BWS/1.0
            < Content-Length: 3342
            < Content-Type: text/html
            < Cache-Control: private
            < Expires: Thu, 25 Sep 2008 05:14:30 GMT
            < Set-Cookie: BAIDUID=3A8165EF68FFEE5F605D33ADEF300BA1:FG=1; expires=Thu, 25-Sep-38 05:14:30 GMT; path=/; domain=.baidu.com
            < P3P: CP=" OTI DSP COR IVA OUR IND COM "
            <
            <html><head><meta http-equiv=Content-Type content="text/html;charset=gb2312"><title>......

            1.狀態(tài)行
            由三個標(biāo)記組成:HTTP版本、響應(yīng)代碼和響應(yīng)描述
            HTTP版本:: 向客戶端指明其可理解的最高版本。
            響應(yīng)代碼:: 3位的數(shù)字代碼,指出請求的成功或失敗,如果失敗則指出原因。
            響應(yīng)描述:: 為響應(yīng)代碼的可讀性解釋。

            < HTTP/1.1 200 OK

            HTTP響應(yīng)碼劃分如下(祥見后):
            1xx:信息,請求收到,繼續(xù)處理
            2xx:成功,行為被成功地接受、理解和采納
            3xx:重定向,為了完成請求,必須進(jìn)一步執(zhí)行的動作
            4xx:客戶端錯誤


            2.響應(yīng)頭
            跟請求頭一樣,它們指出服務(wù)器的功能,標(biāo)識出響應(yīng)數(shù)據(jù)的細(xì)節(jié)。

            3.空行
            最后一個響應(yīng)頭標(biāo)之后是一個空行,發(fā)送回車符和退行,表明服務(wù)器以下不再有頭標(biāo)。

            4.響應(yīng)數(shù)據(jù)
            HTML文檔和圖像等,就是HTML本身。


            = HTTP頭
            用以描述客戶端或者服務(wù)器的屬性、被傳輸?shù)馁Y源等, 分為
            1.通用頭標(biāo):即可用于請求,也可用于響應(yīng),是作為一個整體而不是特定資源與事務(wù)相關(guān)聯(lián)。
            2.請求頭標(biāo):允許客戶端傳遞關(guān)于自身的信息和希望的響應(yīng)形式。
            3.響應(yīng)頭標(biāo):服務(wù)器和于傳遞自身信息的響應(yīng)。
            4.實體頭標(biāo):定義被傳送資源的信息。即可用于請求,也可用于響應(yīng)。

            下表描述在HTTP/1.1中用到的頭標(biāo)
            Accept   定義客戶端可以處理的媒體類型,按優(yōu)先級排序;
              在一個以逗號為分隔的列表中,可以定義多種類型和使用通配符。例如:Accept: image/jpeg,image/png,*/*
            Accept-Charset  定義客戶端可以處理的字符集,按優(yōu)先級排序;
              在一個以逗號為分隔的列表中,可以定義多種類型和使用通配符。例如:Accept-Charset: iso-8859-1,*,utf-8
            Accept-Encoding 定義客戶端可以理解的編碼機制。例如:Accept-Encoding:gzip,compress
            Accept-Language 定義客戶端樂于接受的自然語言列表。例如:Accept-Language: en,de
            Accept-Ranges  一個響應(yīng)頭標(biāo),它允許服務(wù)器指明:將在給定的偏移和長度處,為資源組成部分的接受請求。
              該頭標(biāo)的值被理解為請求范圍的度量單位。例如Accept-Ranges: bytes或Accept-Ranges: none
            Age   允許服務(wù)器規(guī)定自服務(wù)器生成該響應(yīng)以來所經(jīng)過的時間長度,以秒為單位。
              該頭標(biāo)主要用于緩存響應(yīng)。例如:Age: 30
            Allow   一個響應(yīng)頭標(biāo),它定義一個由位于請求URI中的次源所支持的HTTP方法列表。例如:Allow: GET,PUT
            AUTHORIZATION  一個響應(yīng)頭標(biāo),用于定義訪問一種資源所必需的授權(quán)(域和被編碼的用戶ID與口令)。
              例如:Authorization: Basic YXV0aG9yOnBoaWw=
            Cache-Control  一個用于定義緩存指令的通用頭標(biāo)。例如:Cache-Control: max-age=30
            Connection  一個用于表明是否保存socket連接為開放的通用頭標(biāo)。例如:Connection: close或Connection: keep-alive
            Content-Base  一種定義基本URI的實體頭標(biāo),為了在實體范圍內(nèi)解析相對URLs。
              如果沒有定義Content-Base頭標(biāo)解析相對URLs,使用Content-Location URI(存在且絕對)或使用URI請求。
              例如:Content-Base: Http://www.myweb.com
            Content-Encoding 一種介質(zhì)類型修飾符,標(biāo)明一個實體是如何編碼的。例如:Content-Encoding: zip
            Content-Language 用于指定在輸入流中數(shù)據(jù)的自然語言類型。例如:Content-Language: en
            Content-Length 指定包含于請求或響應(yīng)中數(shù)據(jù)的字節(jié)長度。例如:Content-Length:382
            Content-Location 指定包含于請求或響應(yīng)中的資源定位(URI)。
              如果是一絕。對URL它也作為被解析實體的相對URL的出發(fā)點。
              例如:Content-Location: http://www.myweb.com/news
            Content-MD5  實體的一種MD5摘要,用作校驗和。
              發(fā)送方和接受方都計算MD5摘要,接受方將其計算的值與此頭標(biāo)中傳遞的值進(jìn)行比較。
              例如:Content-MD5: <base64 of 128 MD5 digest>
            Content-Range  隨部分實體一同發(fā)送;標(biāo)明被插入字節(jié)的低位與高位字節(jié)偏移,也標(biāo)明此實體的總長度。
              例如:Content-Range: 1001-2000/5000
            Contern-Type  標(biāo)明發(fā)送或者接收的實體的MIME類型。例如:Content-Type: text/html
            Date   發(fā)送HTTP消息的日期。例如:Date: Mon,10PR 18:42:51 GMT
            ETag   一種實體頭標(biāo),它向被發(fā)送的資源分派一個唯一的標(biāo)識符。
              對于可以使用多種URL請求的資源,ETag可以用于確定實際被發(fā)送的資源是否為同一資源。
              例如:ETag: "208f-419e-30f8dc99"
            Expires  指定實體的有效期。例如:Expires: Mon,05 Dec 2008 12:00:00 GMT
            Form   一種請求頭標(biāo),給定控制用戶代理的人工用戶的電子郵件地址。例如:From: webmaster@myweb.com
            Host   被請求資源的主機名。對于使用HTTP/1.1的請求而言,此域是強制性的。例如:Host: www.myweb.com
            If-Modified-Since 如果包含了GET請求,導(dǎo)致該請求條件性地依賴于資源上次修改日期。
              如果出現(xiàn)了此頭標(biāo),并且自指定日期以來,此資源已被修改,應(yīng)該反回一個304響應(yīng)代碼。
              例如:If-Modified-Since: Mon,10PR 18:42:51 GMT
              If-Match 如果包含于一個請求,指定一個或者多個實體標(biāo)記。只發(fā)送其ETag與列表中標(biāo)記區(qū)配的資源。
              例如:If-Match: "208f-419e-308dc99"
              If-None-Match 如果包含一個請求,指定一個或者多個實體標(biāo)記。資源的ETag不與列表中的任何一個條件匹配,操作才執(zhí)行。
              例如:If-None-Match: "208f-419e-308dc99"
            If-Range  指定資源的一個實體標(biāo)記,客戶端已經(jīng)擁有此資源的一個拷貝。必須與Range頭標(biāo)一同使用。
              如果此實體自上次被客戶端檢索以來,還不曾修改過,那么服務(wù)器只發(fā)送指定的范圍,否則它將發(fā)送整個資源。
              例如:Range: byte=0-499<CRLF>If-Range:"208f-419e-30f8dc99"
            If-Unmodified-Since 只有自指定的日期以來,被請求的實體還不曾被修改過,才會返回此實體。
              例如:If-Unmodified-Since:Mon,10PR 18:42:51 GMT
            Last-Modified  指定被請求資源上次被修改的日期和時間。例如:Last-Modified: Mon,10PR 18:42:51 GMT
            Location  對于一個已經(jīng)移動的資源,用于重定向請求者至另一個位置。
              與狀態(tài)編碼302(暫時移動)或者301(永久性移動)配合使用。
              例如:Location: http://www2.myweb.com/index.jsp
            Max-Forwards  一個用于TRACE方法的請求頭標(biāo),以指定代理或網(wǎng)關(guān)的最大數(shù)目,該請求通過網(wǎng)關(guān)才得以路由。
              在通過請求傳遞之前,代理或網(wǎng)關(guān)應(yīng)該減少此數(shù)目。例如:Max-Forwards: 3
            Pragma   一個通用頭標(biāo),它發(fā)送實現(xiàn)相關(guān)的信息。例如:Pragma: no-cache
            Proxy-Authenticate 類似于WWW-Authenticate,便是有意請求只來自請求鏈(代理)的下一個服務(wù)器的認(rèn)證。
              例如:Proxy-Authenticate: Basic realm-admin
            Proxy-Proxy-Authorization 類似于授權(quán),但并非有意傳遞任何比在即時服務(wù)器鏈中更進(jìn)一步的內(nèi)容。
              例如:Proxy-Proxy-Authorization: Basic YXV0aG9yOnBoaWw=
            Public   列表顯示服務(wù)器所支持的方法集。例如:Public: OPTIONS,MGET,MHEAD,GET,HEAD
            Range   指定一種度量單位和一個部分被請求資源的偏移范圍。例如:Range: bytes=206-5513
            Refener  一種請求頭標(biāo)域,標(biāo)明產(chǎn)生請求的初始資源。對于HTML表單,它包含此表單的Web頁面的地址。
              例如:Refener: http://www.myweb.com/news/search.html
            Retry-After  一種響應(yīng)頭標(biāo)域,由服務(wù)器與狀態(tài)編碼503(無法提供服務(wù))配合發(fā)送,以標(biāo)明再次請求之前應(yīng)該等待多長時間。
              此時間即可以是一種日期,也可以是一種秒單位。例如:Retry-After: 18
            Server   一種標(biāo)明Web服務(wù)器軟件及其版本號的頭標(biāo)。例如:Server: Apache/2.0.46(Win32)
            Transfer-Encoding 一種通用頭標(biāo),標(biāo)明對應(yīng)被接受方反向的消息體實施變換的類型。例如:Transfer-Encoding: chunked
            Upgrade  允許服務(wù)器指定一種新的協(xié)議或者新的協(xié)議版本,與響應(yīng)編碼101(切換協(xié)議)配合使用。
              例如:Upgrade: HTTP/2.0
            User-Agent  定義用于產(chǎn)生請求的軟件類型(典型的如Web瀏覽器)。
              例如:User-Agent: Mozilla/4.0(compatible; MSIE 5.5; Windows NT; DigExt)
            Vary   一個響應(yīng)頭標(biāo),用于表示使用服務(wù)器驅(qū)動的協(xié)商從可用的響應(yīng)表示中選擇響應(yīng)實體。例如:Vary: *
            Via   一個包含所有中間主機和協(xié)議的通用頭標(biāo),用于滿足請求。例如:Via: 1.0 fred.com, 1.1 wilma.com
            Warning  用于提供關(guān)于響應(yīng)狀態(tài)補充信息的響應(yīng)頭標(biāo)。例如:Warning: 99 www.myweb.com Piano needs tuning
            www-Authenticate 一個提示用戶代理提供用戶名和口令的響應(yīng)頭標(biāo),與狀態(tài)編碼401(未授權(quán))配合使用。響應(yīng)一個授權(quán)頭標(biāo)。
              例如:www-Authenticate: Basic realm=zxm.mgmt

            = HTTP碼應(yīng)碼
            響應(yīng)碼由三位十進(jìn)制數(shù)字組成,它們出現(xiàn)在由HTTP服務(wù)器發(fā)送的響應(yīng)的第一行, 分五種類型,由它們的第一位數(shù)字表示:
            - 1xx:信息,請求收到,繼續(xù)處理
            - 2xx:成功,行為被成功地接受、理解和采納
            - 3xx:重定向,為了完成請求,必須進(jìn)一步執(zhí)行的動作
            - 4xx:客戶端錯誤,請求包含語法錯誤或者請求無法實現(xiàn)
            - 5xx:服務(wù)器錯誤,服務(wù)器不能實現(xiàn)一種明顯無效的請求

            下表顯示每個響應(yīng)碼及其含義:
            100 繼續(xù)
            101 分組交換協(xié)
            200 OK
            201 被創(chuàng)建
            202 被采納
            203 非授權(quán)信息
            204 無內(nèi)容
            205 重置內(nèi)容
            206 部分內(nèi)容
            300 多選項
            301 永久地傳送
            302 找到
            303 參見其他
            304 未改動
            305 使用代理
            307 暫時重定向
            400 錯誤請求
            401 未授權(quán)
            402 要求付費
            403 禁止
            404 未找到
            405 不允許的方法
            406 不被采納
            407 要求代理授權(quán)
            408 請求超時
            409 沖突
            410 過期的
            411 要求的長度
            412 前提不成立
            413 請求實例太大
            414 請求URI太大
            415 不支持的媒體類型
            416 無法滿足的請求范圍
            417 失敗的預(yù)期
            500 內(nèi)部服務(wù)器錯誤
            501 未被使用
            502 網(wǎng)關(guān)錯誤
            503 不可用的服務(wù)
            504 網(wǎng)關(guān)超時
            505 HTTP版本未被支持


            = 實例

            == POST 數(shù)據(jù)

            == 上傳一個文件
            假設(shè)接受文件的網(wǎng)頁程序位于 a
            bb
            ccc

            客戶端鏈接 192.168.29.65 后, 應(yīng)該發(fā)送如下http 請求:
            POST /upload_file/UploadFile HTTP/1.1
            Accept: text/plain, */*
            Accept-Language: zh-cn
            Host: 192.168.29.65
            Content-Type:multipart/form-data;boundary=---------------------------7d33a816d302b6
            User-Agent: Mozilla/4.0 (compatible; OpenOffice.org)
            Content-Length: 333
            Connection: Keep-Alive

            -----------------------------7d33a816d302b6
            Content-Disposition: form-data; name="userfile1"; filename="E:s"
            Content-Type: application/octet-stream
            a
            bb
            ccc
            -----------------------------7d33a816d302b6
            Content-Disposition: form-data; name="text1"
            foo
            -----------------------------7d33a816d302b6
            Content-Disposition: form-data; name="password1"
            bar
            -----------------------------7d33a816d302b6--

            (上面有一個回車)

            此內(nèi)容必須一字不差,包括最后的回車。
            注意:Content-Length: 333 這里的333是紅色內(nèi)容的總長度(包括最后的回車)
            注意這一行:
            Content-Type: multipart/form-data; boundary=---------------------------7d33a816d302b6
            根據(jù) rfc1867, multipart/form-data是必須的.
            ---------------------------7d33a816d302b6 是分隔符,分隔多個文件、表單項。其中33a816d302b6 是即時生成的一個數(shù)字,用以確保整個分隔符不會在文件或表單項的內(nèi)容中出現(xiàn)。Form每個部分用分隔符分割,分隔符之前必須加上"--"著兩個字符(即--{boundary})才能被http協(xié)議認(rèn)為是Form的分隔符,表示結(jié)束的話用在正確的分隔符后面添加"--"表示結(jié)束。

            前面的 ---------------------------7d 是 IE 特有的標(biāo)志,Mozila 為---------------------------71.
            每個分隔的數(shù)據(jù)的都可以用Content-Type來表示下面數(shù)據(jù)的類型,可以參考rfc1341 (
            http://www.ietf.org/rfc/rfc1341.txt) 例如:
            Contect-Type:application/octet-stream 表示下面的數(shù)據(jù)是二進(jìn)制數(shù)據(jù)
            Contect-Type:text/plain 表示下面的數(shù)據(jù)是ASSCII碼數(shù)據(jù)
            Contect-Type:text/richtext 表示下面的數(shù)據(jù)是RTF格式

            posted @ 2008-09-25 14:05 泡泡牛 閱讀(3280) | 評論 (1)編輯 收藏

            2008年8月14日

            在 C++ 中使用 Python script

            想要在c++ 中嵌入script 代碼, 除了自己寫腳本引擎外, lua, python 都可以在c++ 中使用, 另外 MonoBind, AngelScript library 都是一些c++ script library, 可以嵌入到c++ 中使用 .
            今天在c++ 中試著嵌入 python 代碼 (示例代碼在 Python-2.5.2\Demo\embed\ 下)

            #include <Python.h>
            int main(int argc, char *argv[])
            {
              
            // Py_NoSiteFlag = 1;
              
            // Py_SetPythonHome("D:\\usr\\Python"); // PYTHONHOME

              Py_Initialize();
              PyRun_SimpleString(
            "from time import time,ctime\n"
                                 
            "print 'Today is',ctime(time())\n");
              Py_Finalize();
              
            return 0;
            }

            在運行時可能會產(chǎn)生類似 'import site' failed; use -v for traceback 的錯誤, 原因是python 在import module 的時候的路徑問題. 有3種方法可以解決(以前通過設(shè)置環(huán)境變量 PYTHONPATH 好像在2.5 已經(jīng)無效了).
            0. 取消注釋 Py_NoSiteFlag = 1;
            這個只是取消import site , 當(dāng)然如果在代碼中要import 啥的話, 還是會出現(xiàn)錯誤的.
            a. 設(shè)置環(huán)境變量 PYTHONHOME = D:\usr\Python 
            b. 在調(diào)用 Py_Initialize 之前調(diào)用函數(shù)
            Py_SetPythonHome("D:\\usr\\Python");  // 參數(shù)是python 的安裝目錄

            2. 其他一些有用的資源
            Python/C API Reference Manual (API 參考) ,  Extending and Embedding the Python Interpreter (擴展及嵌入Python解釋器, 主要說明了如何擴展Python, 給Python 寫擴展, 其中 5. Embedding Python in Another Application  一章講述了在C++中嵌入/調(diào)用Python 代碼 )

            使用C/C++擴展Python  對文 Extending and Embedding the Python Interpreter 作了精簡, 很不錯的一篇文章, 但是跳過了一些基礎(chǔ) .

            Building Hybrid Systems with Boost.Python 介紹了使用boost.python 方便python 插件開發(fā), python綁定c++程序 是其中文版本.

            Embedding Python in Multi-Threaded C/C++ Applications 講了c++在多線程環(huán)境如何使用Python , 文 C++多線程中調(diào)用python api函數(shù) 提供了一個多線程的封裝.

            SCXX - A Simple Python/C++ API
            http://davidf.sjsoft.com/mirrors/mcmillan-inc/scxx.html

            C++擴展和嵌入Python應(yīng)用 (介紹了一些Python/C API 函數(shù), 以及ext 例子, 一般般)
            http://hi.baidu.com/yunsweet/blog/item/20b08aeebaa2b1282cf534c7.html


            3. Python 多線程的使用

            zz http://blog.csdn.net/liguangyi/archive/2007/06/20/1659697.aspx 
            今天看了近一天關(guān)于多線程的應(yīng)用中,如何安全調(diào)用python方面的資料,開始的時候看的簡直頭大如斗,被python語言的全局鎖(Global Interpreter Lock)、線程狀態(tài)(Thread State )等都有點繞暈了,后來經(jīng)過各方面文章和幫助文檔的相互參考,發(fā)現(xiàn)對于2.4/2.5版本,提供了PyGILState_Ensure, PyGILState_Release,哎,這下可方便大發(fā)了。

            一、首先定義一個封裝類,主要是保證PyGILState_Ensure, PyGILState_Release配對使用,而且這個類是可以嵌套使用的。

            #include <python.h>

            class PyThreadStateLock
            {
            public:
                PyThreadStateLock(void)
                {
                    state = PyGILState_Ensure( );
                }

                ~PyThreadStateLock(void)
                {
                     PyGILState_Release( state );
                }
            private:
                PyGILState_STATE state;
            };


            二、在主線程中,這樣處理

                // 初始化
                Py_Initialize();
                // 初始化線程支持
                PyEval_InitThreads();
                // 啟動子線程前執(zhí)行,為了釋放PyEval_InitThreads獲得的全局鎖,否則子線程可能無法獲取到全局鎖。
                PyEval_ReleaseThread(PyThreadState_Get());
              
                // 其他的處理,如啟動子線程等
                ......
                  
                // 保證子線程調(diào)用都結(jié)束后
                PyGILState_Ensure();
                Py_Finalize();
                // 之后不能再調(diào)用任何python的API

            三、在主線程,或者子線程中,調(diào)用python本身函數(shù)的都采用如下處理

                {
                    class PyThreadStateLock PyThreadLock;
                    // 調(diào)用python的API函數(shù)處理
                    ......
                }

            呵呵,看這樣是否非常簡單了。


            另外還有兩個和全局鎖有關(guān)的宏,Py_BEGIN_ALLOW_THREADS 和 Py_END_ALLOW_THREADS。這兩個宏是為了在較長時間的C函數(shù)調(diào)用前,臨時釋放全局鎖,完成后重新獲取全局鎖,以避免阻塞其他python的線程繼續(xù)運行。這兩個宏可以這樣調(diào)用

                {
                    class PyThreadStateLock PyThreadLock;
                    // 調(diào)用python的API函數(shù)處理
                    ......

                    Py_BEGIN_ALLOW_THREADS
                    // 調(diào)用需要長時間的C函數(shù)
                    ......
                    Py_END_ALLOW_THREADS

                    // 調(diào)用python的API函數(shù)處理
                    ......
                }

            4. 可能的錯誤及解決
            a. 在vs 200x 下 debug 模式出現(xiàn)鏈接問題
            extmodule.obj : error LNK2019: unresolved external symbol __imp___Py_Dealloc referenced in function _PySwigObject_format
            extmodule.obj : error LNK2019: unresolved external symbol __imp___Py_NegativeRefcount referenced in function _PySwigObject_format
            extmodule.obj : error LNK2001: unresolved external symbol __imp___Py_RefTotal
            extmodule.obj : error LNK2019: unresolved external symbol __imp___PyObject_DebugFree referenced in function _PySwigObject_dealloc
            extmodule.obj : error LNK2019: unresolved external symbol __imp___PyObject_DebugMalloc referenced in function _PySwigObject_New
            extmodule.obj : error LNK2019: unresolved external symbol __imp__Py_InitModule4TraceRefs referenced in function _init_extmodule

            主要是因為 Py_DEBUG/Py_TRACE_REFS 引起, 修改 Python\include 下的 pyconfig.h, object.h 兩個文件就行了 ... 詳見 http://www.nabble.com/link-error-in-debug-mode-td3126668.html 

            posted @ 2008-08-14 17:55 泡泡牛 閱讀(10923) | 評論 (4)編輯 收藏
            使用 python 寫 COM

            Python 支持Com調(diào)用(client com) 以及撰寫COM 組件(server com).
            1. com 調(diào)用示例(使用Windows Media Player 播放音樂)

            from win32com.client import Dispatch
            mp 
            = Dispatch("WMPlayer.OCX")
            tune 
            = mp.newMedia("C:/WINDOWS/system32/oobe/images/title.wma")
            mp.currentPlaylist.appendItem(tune)
            mp.controls.play()

            2. com server 的編寫
            主要可以參考 <<Python Programming on Win32 之 Chapter 12 Advanced Python and COM http://oreilly.com/catalog/pythonwin32/chapter/ch12.html >>
            示例(分割字符串)
            - 代碼
            class PythonUtilities:
                _public_methods_ 
            = [ 'SplitString' ]
                _reg_progid_ 
            = "PythonDemos.Utilities"
                
            # NEVER copy the following ID 
                # Use "print pythoncom.CreateGuid()" to make a new one.
                _reg_clsid_ = "{41E24E95-D45A-11D2-852C-204C4F4F5020}"
                
                
            def SplitString(self, val, item=None):
                    
            import string
                    
            if item != None: item = str(item)
                    
            return string.split(str(val), item)
             
            # Add code so that when this script is run by
            #
             Python.exe, it self-registers.
            if __name__=='__main__':
                
            print "Registering COM server"
                
            import win32com.server.register
                win32com.server.register.UseCommandLine(PythonUtilities)

            - 注冊/注銷Com

            Command-Line Option

            Description

             

            The default is to register the COM objects.

            --unregister

            Unregisters the objects. This removes all references to the objects from the Windows registry.

            --debug

            Registers the COM servers in debug mode. We discuss debugging COM servers later in this chapter.

            --quiet

            Register (or unregister) the object quietly (i.e., don't report success).


            - 使用COM
            可以在python 命令行下運行
            >>> import win32com.client
            >>> s = win32com.client.Dispatch("PythonDemos.Utilities")
            >>> s.SplitString("a,b,c"",")
            ((u
            'a', u'a,b,c'),)
            >>>

            3. python server com 原理
            其實在注冊表中查找到python com 的實現(xiàn)內(nèi)幕
            Windows Registry Editor Version 5.00

            [HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}]
            @
            ="PythonDemos.Utilities"

            [HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\Debugging]
            @
            ="0"

            [HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\Implemented Categories]

            [HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\Implemented Categories\{B3EF80D0-68E2-11D0-A689-00C04FD658FF}]

            [HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\InprocServer32]
            @
            ="pythoncom25.dll"
            "ThreadingModel"="both"

            [HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\LocalServer32]
            @
            ="D:\\usr\\Python\\pythonw.exe \"D:\\usr\\Python\\lib\\site-packages\\win32com\\server\\localserver.py\" {41E24E95-D45A-11D2-852C-204C4F4F5020}"

            [HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\ProgID]
            @
            ="PythonDemos.Utilities"

            [HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\PythonCOM]
            @
            ="PythonDemos.PythonUtilities"

            [HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\PythonCOMPath]
            @
            ="D:\\"

            inproc server 是通過pythoncom25.dll 實現(xiàn)
            local server 通過localserver.py 實現(xiàn)
            com 對應(yīng)的python 源文件信息在 PythonCOMPath & PythonCOM

            4. 使用問題
            用PHP 或者 c 調(diào)用com 的時候
            <?php
            $com = new COM("PythonDemos.Utilities");
            $rs = $com->SplitString("a b c");
            foreach($rs as $r)
                
            echo $r."\n";
            ?>
            會碰到下面的一些錯誤.
            pythoncom error: PythonCOM Server - The 'win32com.server.policy' module could not be loaded.
            <type 'exceptions.ImportError'>: No module named server.policy pythoncom error: CPyFactory::CreateInstance failed to create instance. (80004005)


            可以通過2種方式解決:
            a. 設(shè)置環(huán)境 PYTHONHOME = D:\usr\Python
            另外在c ++ 使用python 的時候, 如果import module 出現(xiàn)錯誤 'import site' failed; use -v for traceback 的話, 也可以通過設(shè)置這個變量解決.

            b. 為com 生產(chǎn)exe, dll 可執(zhí)行文件, setup.py 代碼如下 :
            from distutils.core import setup 
            import py2exe 

            import sys 
            import shutil 

            # Remove the build tree ALWAYS do that! 
            shutil.rmtree("build", ignore_errors=True) 

            # List of modules to exclude from the executable 
            excludes = ["pywin""pywin.debugger""pywin.debugger.dbgcon""pywin.dialogs""pywin.dialogs.list"

            # List of modules to include in the executable 
            includes = ["win32com.server"

            # ModuleFinder can't handle runtime changes to __path__, but win32com uses them 
            try
                
            # if this doesn't work, try import modulefinder 
                import py2exe.mf as modulefinder 
                
            import win32com 
                
                
            for p in win32com.__path__[1:]: 
                    modulefinder.AddPackagePath(
            "win32com", p) 
                
                
            for extra in ["win32com.shell""win32com.server"]: #,"win32com.mapi" 
                    __import__(extra) 
                    m 
            = sys.modules[extra] 
                    
            for p in m.__path__[1:]: 
                        modulefinder.AddPackagePath(extra, p) 

            except ImportError: 
                
            # no build path setup, no worries. 
                pass 

            # Set up py2exe with all the options 
            setup( 
                options 
            = {"py2exe": {"compressed"2
                                      
            "optimize"2
                                      
            #"bundle_files": 1, 
                                      "dist_dir""COMDist"
                                      
            "excludes": excludes, 
                                      
            "includes": includes}}, 
                
            # The lib directory contains everything except the executables and the python dll. 
                # Can include a subdirectory name. 
                zipfile = None, 
                com_server 
            = ['PythonDemos'], # 文件名!!
                ) 


            ref:
            http://oreilly.com/catalog/pythonwin32/chapter/ch12.html 
            http://blog.donews.com/limodou/archive/2005/09/02/537571.aspx 

            posted @ 2008-08-14 17:02 泡泡牛 閱讀(6096) | 評論 (0)編輯 收藏
            僅列出標(biāo)題  下一頁
            久久精品国产精品亚洲人人| 久久er国产精品免费观看2| 中文字幕久久亚洲一区| 国内精品伊人久久久久妇| 无遮挡粉嫩小泬久久久久久久| 久久久女人与动物群交毛片| 久久综合九色综合97_久久久| 久久精品亚洲乱码伦伦中文| 久久精品卫校国产小美女| 成人综合伊人五月婷久久| 久久99精品久久久久久不卡| 久久99热这里只有精品国产| 亚洲午夜精品久久久久久人妖| 久久久受www免费人成| 亚洲熟妇无码另类久久久| 99久久国产综合精品网成人影院| 一级A毛片免费观看久久精品| 成人国内精品久久久久影院| 亚洲欧洲久久久精品| 久久超碰97人人做人人爱| 久久亚洲av无码精品浪潮| 99久久成人国产精品免费| 午夜视频久久久久一区| 久久不射电影网| 亚洲午夜无码久久久久| 久久国产视频网| 国产午夜久久影院| 久久久久久久波多野结衣高潮| 97精品伊人久久久大香线蕉 | 国产成人久久久精品二区三区| 亚洲欧洲久久久精品| 曰曰摸天天摸人人看久久久| 狼狼综合久久久久综合网| 久久性生大片免费观看性| 久久精品国产免费一区| 亚洲午夜久久久久妓女影院| 亚洲午夜精品久久久久久app| 国内精品久久久久久久久电影网| 久久久久亚洲AV无码专区体验| 久久丫忘忧草产品| 欧美久久久久久精选9999|