BSTR VARIANT SAFEARRAY
VBScript ではIDispatchインタフェースを使ってCOMサーバを呼出します。
受け渡すパラメータは、VARIANT互換のタイプを使います。
ここではわかりにくいBSTR VARIANT SAFEARRAYを親切に説明。
BSTRの使い方
BSTRは、クライアントとCOMサーバで文字列のやり取りに使います。
ヘッダファイルの定義は、
typedef OLECHAR *BSTR
typedef WCHAR OLECHAR;
typedef unsigned short WCHAR;
となっています。ようするにWCHAR(unsigned short)のポインタです。最初に文字列の長さが入ります。
次のように文字列でパラメータを受取りたいときに使います。
下の例では、UNICODEをASCII に変換しています。
STDMETHODIMP CBasp21::SendMail(BSTR server, BSTR to, BSTR from, BSTR subj, BSTR body, BSTR file, BSTR * pVal)
{
USES_CONVERSION;
LPCSTR szServer = OLE2T(server);
LPCSTR szTo = OLE2T(to);
LPCSTR szFrom = OLE2T(from);
LPCSTR szSubject = OLE2T(subj);
// LPCSTR szBody = OLE2T(body); // スタック オーバフロー防止
int bodylen = (lstrlenW(body)+1)*2;
char *szBody =
ATLW2AHELPER((LPSTR) new char[bodylen], body, bodylen);
LPCSTR szFile = OLE2T(file);
VARIANTの使い方
VARIANTは、クライアントとCOMサーバで文字列、数字、配列などのやり取りに使います。
VARIANTは、さまざまなデータを扱うことができます。
下の例は、sprintfメソッドの実装です。
STDMETHODIMP CBasp21::sprintf(BSTR format, VARIANT args, BSTR * pVal)
{
USES_CONVERSION;
LPSTR szFormat = OLE2T(format);
int len = strlen(szFormat);
if (len == 0) {
*pVal = A2BSTR("");
return S_OK;
}
char tp[4096];
tp[0] = 0;
VARIANT var = args;
VARTYPE vt = V_VT(&var);
// check VARIANT REFERENCE
if (vt == (VT_VARIANT | VT_BYREF)) {
var = *args.pvarVal;
vt = V_VT(&var);
}
try {
int bArray = vt & VT_ARRAY;
if (!bArray) { // not array
while(1) {
if (vt == VT_I2) {
::sprintf(tp,szFormat,var.iVal);
break;
}
if (vt == (VT_I2 | VT_BYREF)) {
::sprintf(tp,szFormat,*var.piVal);
break;
}
if (vt == VT_I4) {
::sprintf(tp,szFormat,var.lVal);
break;
}
if (vt == (VT_I4 | VT_BYREF)) {
::sprintf(tp,szFormat,*var.plVal);
break;
}
if (vt == VT_R4) {
::sprintf(tp,szFormat,var.fltVal);
break;
}
if (vt == (VT_R4 | VT_BYREF)) {
::sprintf(tp,szFormat,*var.pfltVal);
break;
}
if (vt == VT_R8) {
::sprintf(tp,szFormat,var.dblVal);
break;
}
if (vt == (VT_R8 | VT_BYREF)) {
::sprintf(tp,szFormat,*var.pdblVal);
break;
}
if (vt == VT_BSTR) {
::sprintf(tp,szFormat,OLE2T(var.bstrVal));
break;
}
if (vt == (VT_BSTR | VT_BYREF)) {
::sprintf(tp,szFormat,OLE2T(*var.pbstrVal));
break;
}
return E_FAIL;
}
*pVal = A2BSTR(tp);
return S_OK;
}
// array
return E_FAIL;
}
catch (...) {
try {
if (vt == VT_BSTR) {
long num = ::atol(OLE2T(var.bstrVal));
::sprintf(tp,szFormat,num);
return S_OK;
}
if (vt == (VT_BSTR | VT_BYREF)) {
long num = ::atol(OLE2T(*var.pbstrVal));
::sprintf(tp,szFormat,num);
return S_OK;
}
}
catch (...) {
return E_FAIL;
}
return E_FAIL;
}
return S_OK;
}
SAFEARRAYの使い方
SAFEARRAYは、クライアントとCOMサーバで配列のやり取りに使います。
SAFEARRAYは、VARIANTの中のVT_ARRAYタイプとして
使います。
下の例は、SAFEARRAYを使ったReadDirメソッドの実装です。
STDMETHODIMP CBasp21::ReadDir(BSTR dirname, VARIANT * pvaVariant)
{
USES_CONVERSION;
LPSTR name = OLE2T(dirname);
int j;
SAFEARRAYBOUND sabound[1];
SAFEARRAY * psa = NULL;
BSTR bstr = NULL;
HRESULT hr;
VARIANT vtemp;
VariantInit(&vtemp);
V_VT(&vtemp) = VT_BSTR;
hr = VariantClear(pvaVariant);
if (FAILED(hr))
return hr;
CReadDir fdata; // WIN32_FIND_DATA wrrapper class
BArray sortArray;
//ディレクトリの中のファイルの数だけ繰り返す
BOOL more = fdata.First(name);
while (more) {
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED ||
fdata.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM ||
fdata.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY ||
fdata.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {
more = fdata.Next();
continue;
}
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if (*(fdata.cFileName) != '.') {
sortArray.Add(fdata.cFileName);
}
}
else
sortArray.Add(fdata.cFileName);
more = fdata.Next();
}
int nElem = sortArray.GetSize();
char **pdata = sortArray.GetAddr();
// call sort using ascii
QuickSort(pdata, nElem,0,0,0);
V_VT(pvaVariant) = VT_ARRAY | VT_VARIANT;
sabound[0].cElements = nElem ;
sabound[0].lLbound = 0;
psa = SafeArrayCreate(VT_VARIANT, 1, sabound);
if (psa == NULL)
return ResultFromScode(E_OUTOFMEMORY);
LPVARIANT rgElems;
hr= SafeArrayAccessData(psa,(LPVOID*)&rgElems);
if (FAILED(hr))
goto error;
// copy data to safearray
for (j = 0;j < nElem;j++) {
V_BSTR(&vtemp) = A2BSTR(pdata[j]);
rgElems[j] = vtemp;
}
// if we do not issue below, 2nd call fails.
SafeArrayUnaccessData(psa); // unlock array
V_ARRAY(pvaVariant) = psa;
return S_OK;
error:
if (psa) SafeArrayDestroy(psa);
return hr;
}
文書のご使用上の注意
●この文書を元にプログラムを作成して発生した損害に関しては、一切の責任を負いません。
●もし誤りがありましたら気軽にお知らせください。
Home
Copyright 1997 Tatsuo Baba,All rights reserved.