標籤:std sls result sig china 通過 hello var view
轉載自http://blog.chinaunix.net/uid-20787846-id-3530180.html
編譯com的dll
下面簡單介紹一下步驟和注意事項:
- 在VC++ 6.0中,File -> New... 選擇Projects中的"ATL COM AppWizard",填寫工程名稱等。本例中,工程名為"ATLtest"。
- 在"ATL COM AppWizard - Step 1 on 1"對話方塊中,"Server Type" 選擇"Dynamic Link Library (DLL)",之後Finish。
- 在"ClassView"中,右擊"ATLtest",選擇"New ATL Object...",在"ATL Object Wizard"中,選擇預設的"Simple Object",之後"Next"。
- 在"ATL Object Wizard 屬性"中,在"Short Name"輸入介面的名稱。本例中,介面名稱為"test"。之後,"Names"選項卡中的所有textBox都自動填好了預設的值。注意兩個地方:一個"Prog ID"(本例中為"ATLtest.test"),一個"Interface"(本例中為"Itest")。
- 完成之後,在"ClassView"中,"ATLtest classes"下產生了"Ctest"類,並且實現了"Itest"介面。
- 右擊"Itest"介面,選擇"Add Method..."。
- 在"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沒法直接使用。
- 完成這個函數。當然,為了簡單起見,這裡就是給結果隨便賦了一個值,用來說明參數成功的傳遞出來了。沒有考慮任何記憶體流失問題。
//C++ code
STDMETHODIMP Ctest::Encode(
unsigned int msgType,
unsigned int msgLength,
BSTR message,
BSTR *result
)
{
BSTR temp = ::SysAllocString(L"asdfasdf");
*result = temp;
returnS_OK;
}
- 編譯,將得到的ATLtest.dll使用regsvr32進行註冊,之後才能使用COM進行調用。
- 之後書寫這樣的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;
- 注意這裡的"ATLtest.test"是剛才(4)中的"Prog ID",並且使用Encode() 的方法和聲明的也不一樣。沒有關係!
當然,由於完全沒有用到三個輸入參數,這裡的1,1,"11"只是為了滿足輸入參數的數量。
- 這個php的輸出是什麼樣的呢?
//HTML 結果
$result = "未處理的字串"
$result = "asdfasdf"
可見,$result 成功的改變成了dll中賦的值,說明 Encode() 方法成功的返回了值。
幾點疑問
- 為什麼 Encode() 中返回的是 BSTR* ,但是到了php中,就變成了字串(BSTR) 呢?這個自動的轉換是ATL進行的,還是php進行的呢?
- C++代碼中通過SysAllocString()為BSTR分配的空間在何時進行垃圾收集?收集工作由哪裡負責?會不會導致記憶體流失?
- 完惡的C++ 6.0 編譯器,為什麼傳回值不支援 char** 這種簡單的類型呢(使用char**直接編譯出無數錯誤)? BSTR本質上就是指標嘛,也不支援(提示說只支援簡單類型和指標),只好用一個不倫不類的BSTR*來寫。嗯,下一步嘗試改用CCOMBSTR或者_bstr_t,試試哪個更好用。
- 對於傳入的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"找到改庫,並勾上 。
php調用com