php调用com

转载自http://blog.chinaunix.net/uid-20787846-id-3530180.html

编译com的dll

下面简单介绍一下步骤和注意事项:

  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;

    returnS_OK;
    }

  9. 编译,将得到的ATLtest.dll使用regsvr32进行注册,之后才能使用COM进行调用。
  10. 之后书写这样的php代码:

    //php code 
    $com = new COM("ATLtest.test") ordie("无法建立COM组件");
    $result = "未处理的字符串";
    echo‘$result = "‘.$result.‘"
    ‘;

    $result = $com->Encode(1,1,"11");
    echo‘$result = "‘.$result.‘"
    ‘;

    $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在背后做了哪些工作呢?有没有对未被引用的常量"未处理的字符串"进行垃圾收集呢?

PHP调用dll

用DynamicWrapper方法调用。下载DynamicWrapper.dll到php ext下与windows system32下

$dw = new COM("DynamicWrapper");
$dw->Register("EbUsbApi.dll", "EbCreateDataFile", ‘i=sls‘, "f=s", "r=l");
$ch = $dw->EbCreateDataFile("222",11,"22"); #dll其中一个函数
HANDLE EbCreateDataFile(LPCTSTR lpFileName, DWORD dwCreationDisposition, LPCTSTR lpPassword) 

查看CPU荷载:

$wmi = new COM(‘winmgmts://‘);

$processor = $wmi->ExecQuery("SELECT * FROM Win32_Processor");

foreach($processor as $obj){

    $cpu_load_time = $obj->LoadPercentage;

}

echo $cpu_load_time;

调用自定的dll组件:
1) 创建ActiveX dll组件 --

CODE:

Public Function hello() As String
    hello = "Hello World!"
End Function并存为"test.dll" 文件

2) 用regsvr32.exe注册此组件
regsvr32 test.dll

3) 在PHP内调用此dll组件:

$obj = new COM("test.dll");
$output=$obj->hello(); // Call the "hello()" 方法
echo $output; // 显示Hello World! (so this comes from the dll!)

准备工作

比如我作了一个COM组件,新建一个VB6工程,ActiveX Dll将工程命名为P_test,类名为c_test ,类的文件内容如下:

Option Explicit
Private MyScriptingContext As ScriptingContext 
Private MyApplication As Application
Private MyRequest As Request Private MyResponse As Response
Private MyServer As Server 
Private MySession As Session Public

Sub OnStartPage(PassedScriptingContext As ScriptingContext) 
Set MyScriptingContext = PassedScriptingContext 
Set MyApplication = MyScriptingContext.Application 
Set MyRequest = MyScriptingContext.Request 
Set MyResponse = MyScriptingContext.Response 
Set MyServer = MyScriptingContext.Server 
Set MySession = MyScriptingContext.Session 
End Sub

Public Sub OnEndPage() 
Set MyScriptingContext = Nothing
Set MyApplication = Nothing
Set MyRequest = Nothing 
Set MyResponse = Nothing 
Set MyServer = Nothing 
Set MySession = Nothing 
End Sub

Public Function Test_Number(num) As Variant 
If num < 0 Then Get_Number_Attrib ="-1" br style=‘font-size:16px;font-style:normal;font-weight:400;font-family:Verdana;color:rgb(102, 102, 102);‘ />If num > 0 Then Get_Number_Attrib = 1 
If num = 0 Then Get_Number_Attrib = 0 
End Function

编译生成p_test.dll文件

第一步,做为一个COM组件,这个DLL要被系统识别就要先到系统来报到

regsvr32 [路径]/[组件文件名]

regsvr32 C:/WINDOWS/system32/p_test.dll   
   放在系统文件夹system32下不容易出现权限问题

这时候这个文件就不能移动位置了,系统会在用到它时到这个目录来找,如果改目录就得先删除注册

再重新注册

regsvr32 /u [路径]/[组件文件名]

系统会显示窗口表示成功,大意是 组件Dllregister成功或是Dllunregister成功

第二步就可以直接调用它了

$b=new COM("p_test.c_test");  //一般前边是它的主文件名后边是它的类名从注册表里找这个文件可以找到。这样就生成了一个叫b的对象,我们就可以用它的属性和方法来操作了
$a=$b->Test_Number(-454);
echo $a; 

可能遇到的问题是,编译工程时通不过,要将 
Microsoft Active Server Pages Object Library  
引用进来,具体实现"Project->References"找到改库,并勾上 。

时间: 2024-08-26 20:31:32

php调用com的相关文章

微信浏览器中调用支付宝支付

众所周知,在微信浏览器中是无法唤起支付宝的,会提示请在浏览器中打开,如果非要在微信浏览器中调起支付宝的话,只能是跳出微信浏览器,关于这一点,在支付宝官网给出了一个例子.但是,话说回去,后来我仔细想想,其实真的没有必要非要在微信浏览器中调起支付宝支付(当时真是一根筋啊啊啊...) 支付宝手机网站支付的官方文档: https://doc.open.alipay.com/docs/doc.htm?treeId=203&articleId=105288&docType=1 快速接入: https:

c#解决dll调用的问题

在做一个c#中间程序时,调用第三方的dll安装路径"Program Files" 和"Program Files (x86)"的问题,经过一段时间的研究,找到了下面的解决方案: 思路: 1.配置dll的加载路径 2.监控dll 3.dll加载失败判断操作系统位数(x86.x64) 4.动态加载dll 解决方案: 1.在config中添加dll引用配置: <runtime> <assemblyBinding xmlns="urn:schem

调用已发布的WebService

WebService服务演示 登录http://www.webxml.com.cn 单击手机查询服务 3.         选择要调用的方法 例如: getMobileCodeInfo. 4. 输入要查询的手机号单击”调用” 截图如下, 免费用户 UserID为null a)   可以看到返回如下结果: <?xml version="1.0" encoding="utf-8" ?> <string xmlns="http://WebXml

Spring Cloud ZooKeeper集成Feign的坑2,服务调用了一次后第二次调用就变成了500,错误:Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.n

错误如下: 2017-09-19 15:05:24.659 INFO 9986 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.spring[email protected]56528192: startup date [Tue Sep 19 15:05:24 CST 2017]; root of context hierarchy 2017-09-19 15:05:24.858 INFO 9986 --

Spring EL和资源调用

Spring EL-Spring表达式语言,支持在xml和注解中使用表达式,类似于jsp的EL表达式.我们在开发过程中,经常会涉及到调用各种资源,包含普通文本.网址.配置文件.系统环境变量等,我们可以使用Spring的表达式语言来实现资源的注入. Spring主要在注解@Value的参数中使用表达式: (1)注入普通字符 (2)注入操作系统属性 (3)注入表达式运算结果 (4)注入其他Bean的属性 (5)注入文件内容 (6)注入网址内容 (7)注入属性文件 示例代码如下: 1.准备,增加com

微信公众号调用接口返回码

返回码 说明 -1 系统繁忙,此时请开发者稍候再试 0 请求成功 40001 获取access_token时AppSecret错误,或者access_token无效.请开发者认真比对AppSecret的正确性,或查看是否正在为恰当的公众号调用接口 40002 不合法的凭证类型 40003 不合法的OpenID,请开发者确认OpenID(该用户)是否已关注公众号,或是否是其他公众号的OpenID 40004 不合法的媒体文件类型 40005 不合法的文件类型 40006 不合法的文件大小 4000

MVC下微信企业号网页应用开发调用JSSDK接口不成功问题

在MVC下进行企业微信里的网页应用开发,前台页面中为了调用图像接口,使用了JSSDK.按照官方文档进行了正确配置. 现象:WEB开发工具调试一切正常,但从手机企业微信应用进入页面后接口调用无效(这个页面是从一级页面链接过来的),开了调试模式后,显示config:ok.说明配置无误.经过反复检查,终于发现问题所在. 原因:在一级页面(http://xx.xxx.xxx/main/index)中的链接是使用htmlhelper来写的,即@Html.ActionLink("测试接口",&qu

用gson和httpclient调用微信公众平台API

吐槽:微信api很无语,部分用xml,部分用json. 最近在找如何调用微信公众平台关于json相关的api比较方便,最后发现httpcliect和gson不错.如果你有更好的方式,请告诉我. 以下代码先了解如何使用gson和httpclient,有功夫再整到我的sophia里 import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.

微信支付开发(APP)的各种坑,.net和iOS的各种陷阱,解决.net调用下单接口提示无权限,解决iOS跳转到微信支付页面中间只有一个确定按钮

直入主题之前,请容我吐槽一下微*的官方东西:ASDFQ%#$%$#$%^[email protected]#$%DSFQ#$%.......:吐槽玩了!大家心照就好. 要完成手机APP跳转到微信的APP进行微信支付,需要进行如下操作: 1.先去微信的开放平台(http://open.weixin.qq.com)进行开发者账号的注册. 2.新建一个APP应用,然后填写必填信息提交审核. 3.进入APP应用,在接口信息中,进行申请“获得微信支付能力”的功能,期间会提交相关的公司营业信息证明等. 通过

微信公众号API测试——接口调用频率限制

接口频率限制[1] 公众号调用接口并不是无限制的.为了防止公众号的程序错误而引发微信服务器负载异常,默认情况下,每个公众号调用接口都不能超过一定限制,当超过一定限制时,调用对应接口会收到如下错误返回码: {"errcode":45009,"errmsg":"api freq out of limit"} 各接口调用频率限制如下: 接口 每日限额 获取access_token 2000 自定义菜单创建 1000 自定义菜单查询 10000 自定义菜