日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

VC2017下开发ATL程序注意事项

發(fā)布時(shí)間:2024/1/1 c/c++ 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 VC2017下开发ATL程序注意事项 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

VC2017下開(kāi)發(fā)ATL程序注意事項(xiàng)

kagula

2019-4-29

閱讀對(duì)象

? ? ? 早期做過(guò)ATL 項(xiàng)目開(kāi)發(fā)的C++程序員.

?環(huán)境

? ? ?Windows10 Pro, Visual studio 2017/Visual studio 2019, IE11, C++ ATL x86項(xiàng)目.? ? ?

正文

? ? VC2017相對(duì)于VC2013對(duì)ATL開(kāi)發(fā)不是很方便, 因?yàn)椴恢С譃锳TL Simple Object自動(dòng)添加function.

不過(guò)手動(dòng)添加member function也挺簡(jiǎn)單的, 只要三個(gè)步驟就OK了.

? 本文應(yīng)該也適用于從VC2013過(guò)渡到VC2019的C++ ATL程序員.

假設(shè)你已經(jīng)通過(guò)VC2017的wizard添加了名為ZT410的ATL Simple Object.?

第一步:? 在idl文件中定義外部接口

interface IZT410 : IDispatch {HRESULT print([in]BSTR templateName, [in]VARIANT* arrContent, [out, retval]long *result);HRESULT sayHello([in]BSTR msg, [out,retval]BSTR *result); };

通過(guò)wizard建立ZT410后,? ?wizard還會(huì)為你自動(dòng)生成IZT410(接口)代碼.

我為這個(gè)接口添加了print和sayHello方法, 用來(lái)演示ATL參數(shù)如何傳遞.

?

第二步: ZT410 Class中添加方法定義

打開(kāi)ZT410.h找到CZT410 class的聲明, 在public后面添加print和sayHello的方法聲明

public:STDMETHODIMP print(BSTR templateName, VARIANT* arrContent, long *result);STDMETHODIMP sayHello(BSTR msg, BSTR *result);

?

第三步(最后一步)

打開(kāi)ZT410.cpp,? 在里面添加這兩個(gè)member function的實(shí)現(xiàn)

STDMETHODIMP CZT410::print(BSTR templateName, VARIANT* arrContent, long *result)

?

STDMETHODIMP CZT410::sayHello(BSTR msg, BSTR *result) {using namespace std;wstring head = L"收到來(lái)自JavaScript的信息=>";wstring content = head + OLE2W(msg);*result = W2BSTR(content.c_str());return S_OK; }

print的實(shí)現(xiàn)比較復(fù)雜,? 暫時(shí)不貼出來(lái).

現(xiàn)在我們可以測(cè)試了

C#單元測(cè)試

新建C#單元測(cè)試項(xiàng)目, Unit Test Project(.Net Framework),?

Add Reference -> COM -> Type Libraries

you can see snippet below

[TestMethod]public void TestMethod1(){NingboHuashuPrinterLib.ZT410 printer = new NingboHuashuPrinterLib.ZT410();String[] arrContent = { "head", "中文測(cè)試", "tail" };int nResult = printer.print("abc", arrContent);System.Diagnostics.Trace.WriteLine(nResult);}

IE11中JavaScript測(cè)試

<BODY><object classid ="clsid:9bc84eed-d69e-4ef6-8e4e-9d0d615ca08c" id="printer" name="printer"></object><script language ="JavaScript" type="text/javascript">function testSayHelloMethod(){var myArray = ["head","中文測(cè)試","tail"];var a = printer.print("AAA", myArray);alert(a);}</script><input type=button value ="測(cè)試我們的第一個(gè)ATL對(duì)象的方法" onclick="testSayHelloMethod()" /></BODY>

上面的class id指的是coclass ZT410的uuid.

補(bǔ)充

通過(guò)JavaScript向ATL傳遞字符串?dāng)?shù)組, 可不是件簡(jiǎn)單的事,? 下面貼出C++ ATL代碼, 免得同學(xué)們東找西找.

依賴的頭

#include <list> #include <vector> #include <string> #include <sstream>using namespace std;

依賴的函數(shù)

std::string ws2s(const std::wstring& ws) {std::string curLocale = setlocale(LC_ALL, NULL); // curLocale = "C";setlocale(LC_ALL, "chs");const wchar_t* _Source = ws.c_str();size_t _Dsize = 2 * ws.size() + 1;char *_Dest = new char[_Dsize];memset(_Dest, 0, _Dsize);wcstombs(_Dest, _Source, _Dsize);std::string result = _Dest;delete[]_Dest;setlocale(LC_ALL, curLocale.c_str());return result; }CComPtr<IDispatch> VariantToDispatch(__in const CComVariant& var) {if (var.vt == VT_DISPATCH){return var.pdispVal;}return nullptr; }bool VariantToInt(CComVariant varIn, int &nOut) {VARTYPE vtype5;vtype5 = VT_INT;if (varIn.ChangeType(vtype5) == S_OK){nOut = varIn.intVal;return true;}return false; }bool VariantToArray(__in const CComVariant& var, __out vector<CComVariant>& vecVars) {// convert variant to dispatch objectCComPtr<IDispatch> pDispatch = VariantToDispatch(var);if (!pDispatch)return false;// get DISPID of length parameter from array objectLPOLESTR sLengthName = L"length";DISPID dispidLength = 0;HRESULT hr = pDispatch->GetIDsOfNames(IID_NULL, &sLengthName, 1, LOCALE_USER_DEFAULT, &dispidLength);if (FAILED(hr))return false;// get the number of elements using the DISPID of length parameterCComVariant varLength;DISPPARAMS dispParams = { 0 };hr = pDispatch->Invoke(dispidLength, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispParams, &varLength, NULL, NULL);if (FAILED(hr))return false;int nLength = 0; // length of the arraybool bGotInt = VariantToInt(varLength, nLength);if (!bGotInt)return false;// get items of arrayfor (int i = 0; i < nLength; ++i){// get DISPID of item[i] from array objectwstring strIndex = std::to_wstring(i);DISPID dispidIndex = 0;LPOLESTR pIndex = reinterpret_cast<LPOLESTR>(const_cast<WCHAR *>(strIndex.data()));hr = pDispatch->GetIDsOfNames(IID_NULL, &pIndex, 1, LOCALE_USER_DEFAULT, &dispidIndex);if (FAILED(hr))continue;CComVariant varItem;hr = pDispatch->Invoke(dispidIndex, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispParams, &varItem, NULL, NULL);if (FAILED(hr))continue;vecVars.push_back(varItem);}return true; }

現(xiàn)在我們調(diào)用上面的函數(shù),實(shí)現(xiàn)對(duì)字符串?dāng)?shù)組的讀取

STDMETHODIMP CZT410::print(BSTR templateName, VARIANT* arrContent, long *result) {//string strTemplateName;[templateName, &strTemplateName]() {}();//list<string> listContent;[arrContent, &listContent]() {if (arrContent->vt == (VT_ARRAY | VT_BSTR)){//CSharp caller branch.//retrieve array sizelong *larr;long i;long lbound, ubound;::SafeArrayGetUBound(arrContent->parray, 1, &ubound);//inarr->parray就是safearray,第二個(gè)參數(shù)是第幾維度::SafeArrayGetLBound(arrContent->parray, 1, &lbound);const long arrSize = ubound - lbound + 1;#ifdef _DEBUGchar buffer[64] = { 0 };snprintf(buffer, sizeof(buffer), "%d %d", arrSize, arrContent->vt);MessageBoxA(NULL, buffer, NULL, 0); #endif//使用SafeArrayAccessData方法, 取出字符串元素, C#中測(cè)試通過(guò)BSTR HUGEP *pData;SafeArrayAccessData(arrContent->parray, (void HUGEP* FAR*)&pData);for (long i = lbound; i <= ubound; i++){BSTR pBSTR = pData[i];wstring wsTemp = pBSTR;listContent.push_back(ws2s(wsTemp));}SafeArrayUnaccessData(arrContent->parray);}else if (arrContent->vt == VT_DISPATCH){//JS caller branch.CComVariant ccv;vector<CComVariant> vecVars;ccv.Attach(arrContent);VariantToArray(ccv, vecVars);ccv.Detach(arrContent);for (vector<CComVariant>::iterator iter = vecVars.begin(); iter < vecVars.end(); iter++){if (iter->vt == VT_BSTR){std::wstring wsTemp = (LPCTSTR)iter->bstrVal;listContent.push_back(ws2s(wsTemp));}}//for}//if//不知道為什么使用SafeArrayGetElement方法取不出字符串元素.}();#ifdef _DEBUGstringstream ss;for (list<string>::iterator iter = listContent.begin(); iter != listContent.end(); iter++){ss << iter->c_str() << " ";} #endif//對(duì)listContent中的字符串進(jìn)行處理.//...ignore...//返回listContent中字符串的個(gè)數(shù).*result = listContent.size();return S_OK; }

注意事項(xiàng)

? ?上面的ws2s的實(shí)現(xiàn)已經(jīng)過(guò)時(shí),? ?有時(shí)間修改為C++11的實(shí)現(xiàn)方式.

總結(jié)

以上是生活随笔為你收集整理的VC2017下开发ATL程序注意事项的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。