小雨 さんのプロフィールbiggates难得更新的网页ブログリストつながり ツール ヘルプ
    2007/12/08

    php调用dll经验小结

          最近做一个网站,需要频繁使用远程数据,数据接口已经做好。在做转换的时候遇到了性能上的问题:开始打算用php来实现转换,苦苦查了数天,都没有找到直接操作字节的方法。虽然可以使用 pack() 方法将各个数据压入结构中,但是在解压的时候却不能通过 unpack() 简单的解出来,需要通过

    //php code
    for( $i = 0; $i < $length; $i+=2 ){
        $tempstr = $tempstr.chr( hexdec(substr($array["data"], $i, 2)) );
    }
    $array["data"] = $tempstr;

          这类方法进行解码。频繁的使用各种字符串操作,无疑将对性能造成很大的影响。经过研究,发现有以下方法可以实现对字节的操作:

    • 使用stream进行读写
    • 使用socket进行读写
    • 使用COM dll,将数据在C++ dll中进行转换

          由于网上找不到相关的文档(其实是没好好找),stream和socket先后被PASS掉了。为了编译COM的dll,还专门下载了VC++ 6.0(为啥不装2005?硬盘太小,装不下,没办法啊)。经过无穷无尽的Google(全是php调用VB写的dll的信息,没多大帮助)和编译/调试,终于成功的把结果传递到php中。
          下面简单介绍一下步骤和注意事项

    1. 在VC++ 6.0中,File -> New...  选择Projects中的"ATL COM AppWizard",填写工程名称等。本例中,工程名为"ATLtest"。
    2. 在"ATL COM AppWizard - Step 1 on 1"对话框中,"Server Type" 选择"Dynamic Link Library (DLL)",之后Finish。
    3. 在"ClassView"中,右击"ATLtest",选择"New ATL Object...",在"ATL Object Wizard"中,选择默认的"Simple Object",之后"Next"。
    4. 在"ATL Object Wizard 属性"中,在"Short Name"输入接口的名称。本例中,接口名称为"test"。之后,"Names"选项卡中的所有textBox都自动填好了默认的值。注意两个地方:一个"Prog ID"(本例中为"ATLtest.test"),一个"Interface"(本例中为"Itest")。
    5. 完成之后,在"ClassView"中,"ATLtest classes"下生成了"Ctest"类,并且实现了"Itest"接口。
    6. 右击"Itest"接口,选择"Add Method..."。
    7. 在"Add Method to Interface"中,填写方法的名称和参数。注意:返回值一定是HRESULT型,真正的返回值是最后一个参数。比如

      //C++ code
      BSTR Encode(unsigned int msgType, unsigned int msgLength, BSTR message)

      这个函数,要写成

      //C++ code
      STDMETHODIMP Ctest::Encode(
          unsigned int
      msgType,
          unsigned int
      msgLength,
          BSTR message,
          BSTR *result
      )

      这样的形式。还有就是返回值只接受简单的类型(不知道为什么,char**不能用)和指针,BSTR没法直接使用。
    8. 完成这个函数。当然,为了简单起见,这里就是给结果随便赋了一个值,用来说明参数成功的传递出来了。没有考虑任何内存泄漏问题。

      //C++ code
      STDMETHODIMP Ctest::Encode(
          unsigned int
      msgType,
          unsigned int
      msgLength,
          BSTR message,
          BSTR *result
      )
      {
          BSTR temp = ::SysAllocString(L"asdfasdf");
          *result = temp;

          return S_OK;
      }
    9. 编译,将得到的ATLtest.dll使用regsvr32进行注册,之后才能使用COM进行调用。
    10. 之后书写这样的php代码:
      //php code
      $com = new COM("ATLtest.test") or die("无法建立COM组件");
      $result = "未处理的字符串";
      echo '$result = "'.$result.'"<br />';

      $result = $com->Encode(1,1,"11");
      echo '$result = "'.$result.'"<br />';

      $com = null;
    11. 注意这里的"ATLtest.test"是刚才(4)中的"Prog ID",并且使用Encode() 的方法和声明的也不一样。没有关系!
      当然,由于完全没有用到三个输入参数,这里的1,1,"11"只是为了满足输入参数的数量。
    12. 这个php的输出是什么样的呢?

      //HTML 结果
      $result = "未处理的字符串"
      $result = "asdfasdf"

      可见,$result 成功的改变成了dll中赋的值,说明 Encode() 方法成功的返回了值。

    几点疑问

    1. 为什么 Encode() 中返回的是 BSTR* ,但是到了php中,就变成了字符串(BSTR) 呢?这个自动的转换是ATL进行的,还是php进行的呢?
    2. C++代码中通过SysAllocString()为BSTR分配的空间在何时进行垃圾收集?收集工作由哪里负责?会不会导致内存泄漏?
    3. 完恶的C++ 6.0 编译器,为什么返回值不支持 char** 这种简单的类型呢(使用char**直接编译出无数错误)? BSTR本质上就是指针嘛,也不支持(提示说只支持简单类型和指针),只好用一个不伦不类的BSTR*来写。嗯,下一步尝试改用CCOMBSTR或者_bstr_t,试试哪个更好用。
    4. 对于传入的BSTR* result,需要使用 SysFreeString() 进行处理么?在C++中看来,无疑是需要释放的;但是php在背后做了哪些工作呢?有没有对未被引用的常量"未处理的字符串"进行垃圾收集呢?

    参考资料
         
    以下资料比较有参考价值:

    コメント (6 件)

    しばらくお待ちください。
    入力されたコメントは長すぎます。短くしてください。
    何も入力されていません。もう一度やり直してください。
    現在、コメントを追加できません。後でもう一度やり直してください。
    コメントと書くには、保護者 (ほごしゃ) の方の許可 (きょか) をもらってください。許可をリクエストする
    保護者 (ほごしゃ) の方が、あなたがコメントを書けないようにしています。
    現在、コメントを削除できません。後でもう一度やり直してください。
    1 日に投稿できるコメントの最大数を超えました。24 時間経過してから、もう一度やり直してください。
    あなたが他のユーザーに対して迷惑行為を行っている可能性があると確認されたため、お使いのアカウントによるコメントの投稿を無効にしています。誤って無効にされたと思われる場合は、Windows Live のサポートにお問い合わせください。
    コメントを投稿する前に、以下のセキュリティ チェックを完了してください。
    セキュリティ チェックに入力する文字は、画像に表示されている文字または音声で流れた文字と一致していなければいけません。

    コメントを投稿するには、お使いの Windows Live ID でサインインしてください (Hotmail、Messenger、または Xbox LIVE を既に使用している場合は、そのアカウントが Windows Live ID です)。サインイン


    Windows Live ID をお持ちでない場合は、アカウントを新規登録してください。

    名前なしさんの投稿:
    上海拉拉钢膜结构公司是一家专门主要从事建筑 http://www.lalamo.net/ 膜结构 上海上海宇栾钢 http://www.yuluan.sh.cn/ 膜结构公司 。

    上海海洋泵阀制造有限公司是专业生产 http://www.sea-pump.com/dj/ 多级泵 , http://www.sea-pump.com/gm/ 隔膜泵 , http://www.sea-pump.com/hg/ 化工泵 , http://www.sea-pump.com/pw/ 排污泵 , http://www.sea-pump.com/xf/ 消防泵 的大型股份企业,本公司生产的消防泵,排污泵,化工泵,隔膜泵,多级泵已广泛应用于城市给排水、城市污水处理以及国家大型环保处理工程;高层建筑增压送水,园林喷灌、消防增压、远距送水、农田排灌、纺织、造纸工业排水增压以及其他工业增压配套等。产品质量稳定可靠,远销西欧,东南亚,深受广大用户信赖和好评。

    上海上一泵业制造有限公司是中国最大的 http://www.shangyi-pump.com/xf/ 消防泵 , http://www.shangyi-pump.com/pw/ 排污泵 , http://www.shangyi-pump.com/hg/ 化工泵 , http://www.shangyi-pump.com/gm/ 隔膜泵 , http://www.shangyi-pump.com/dj/ 多级泵 制造商之一,在离心历史背景制造领域,是专业生产消防泵,排污泵,化工泵,隔膜泵,多级泵、生活消防成套智能控制给水设备及水泵智能电气控制设备的大型股份制企业

    全采建筑工程设计有限公司专业从事 http://www.qc-design.cn 上海室内设计 ,上海装潢设计,系专业建筑室内设计机构,着力为社会提供私人住宅上海室内设计、上海装潢设计和施工服务以及公共建筑室内设计和施工服务,“全采设计”吸纳志同道合的设计师加入设计团队,其各怀绝技各有所长,从室内设计之结构、造型、色彩、材质、灯光 、配饰等各个方面给予设计团队最专业的技术支持。

    E-LIKES(依莱特斯) http://www.e-likes.com/ 干洗店 、干洗加盟中心,是源自欧洲概念的先进洗涤服务终端。其清新的形象、专业的服务、专业的干洗加盟,正如其天使般的名字一样,依莱特斯干洗店深受都市人群的喜爱,欢迎加入依莱特斯干洗加盟中心 http://www.shjy.sh.cn/ 干洗 , http://www.shjy.sh.cn/ganxijiameng/ 干洗加盟

    上海青浦莲盛专业生产 http://www.915p.com/nijiangbeng/ 泥浆泵 , http://www.915p.com/xiaofangbeng/ 消防泵 , http://www.915p.com/lixinbeng/ 管道离心泵 ,严格经过检验的磁力泵产品广泛应用于市政建设、农田水利、火力发电、石油化工、冶金矿山、消防环保、医药等各个领域,公司本着用心制造泥浆泵,消防泵,用情服务为宗旨愿与各界新老朋友携手共进,竭诚合作,共同创造水泵业界新的辉煌,欢迎广大新老客户前来订购泥浆泵,消防泵。

    Welcome to http://www.mygamebuy.com http://www.mygamebuy.com/ Buy Wow Gold , We will serve you with cheap wow gold , If you want to buy cheap wow gold, please come here , the best price and services are waiting for you Buy Wow Gold http://www.ogamebay.com/ Buy Wow Gold http://www.ogamebay.com/FFXI-Gil/ FFXI Gil .

    上海舒创模型广告制作有限公司,是美国Creator Models 直接领导下的企业,是国内最具创新力的专业 http://www.shuchuang.sh.cn 上海模型 , http://www.shuchuang.sh.cn/cb.html 船舶模型 , http://www.shuchuang.sh.cn/jx.html 机械模型 , http://www.shuchuang.sh.cn/gy.html 工业模型 公司,在不断发展的趋势下,我们为全国各大设计研究院,制造厂商,博物馆,企业展厅,军区,职业技能学校, http://www.200100.net/ IC卡 , http://www.shtiannian.com/ 发光字
    http://www.shtiannian.com/led/ LED显示屏制作
    http://www.dragonwan.com/ 平衡阀
    http://www.dragonwan.com/ Honeywell
    http://www.shjy.sh.cn/ganxi/ 干洗机价格
    http://www.021yajiale.com/balcony/ 无框阳台窗
    http://www.021yajiale.com/sun/ 上海阳光房
    http://www.021yajiale.com 无框阳台
    http://www.021yajiale.com/cell/ 上海纱窗
    http://www.021yajiale.com/product1/ 封阳台
    http://www.yongxutang.com 保健 ,房产开发商及其他事业单位制作了大量模型。

    7 月 9 日
    胡 恩召さんの投稿:
    请问,函数Encode(unsigned int msgType, unsigned int msgLength, BSTR message, BSTR *result)是4个个参数,调用时怎么变成3个$com->Encode(1,1,"11")了???我把你的例子照着做了一遍,就最后的调用这一部出错了,无法显示,就是调用函数的事情。

    请指教

    php中没有指针,但是com组件的一个参数必须为指针,所以怎么解决这个调用的参数问题,请指教啊,

    谢谢,比较急用,发enzhaohoo@gmail.com 吧,非常感谢

    3 月 16 日
    名前なしさんの投稿:
    A friend to buy wow goldTo wow power leveling?On the world's most concessions to the most reputable sites under the single!
    9 月 18 日
    名前なしさんの投稿:

    Hi,Do you have mp4 used LCD monitors, second hand lcd monitors and second hand flat screens? Please go here:www.sstar-hk.com(Southern Stars).We are constantly buying re-usable LCD panels,LCD recycle.The re-usable panels go through strictly designed process of categorizing, checking, testing, repairing and refurbishing before they are re-used to make remanufactured LCD displays and TV sets.Due to our recent breakthrough in testing and repairing technology of LCD, we can improve the value for your LCD panels.

    Contact Us

    E-mail:sstar@netvigator.com
    website:www.sstar-hk.com[cbcbefea

    8 月 30 日
    名前なしさんの投稿:
    Welcome to enter (wow gold) and (wow power leveling) trading site, (wow gold) are cheap, (wow power leveling) credibility Very good! Quickly into the next single! Key words directly to the website click on transactions! -458586142073669
    8 月 22 日
    郭 小雨さんの投稿:
    强烈BS Windows Live Spaces,居然不支持div标签
    我好不容易编辑的代码加亮的文档啊……就这么被吃了
    12 月 8 日

    トラックバック

    この記事のトラックバックの URL は次のとおりです。
    http://biggates.spaces.live.com/blog/cns!715707C35A631274!636.trak
    この記事を参照しているブログ
    • なし