はじめに
WindowsにはWindows Scriptと呼ばれるスクリプトを実行するインフラが用意されており、VBScriptとJScriptという2つのスクリプト言語が搭載されています。
本稿ではC++で書かれたネイティブアプリケーションからJScriptを実行し、JScriptからC++のクラスメソッドを呼び出す方法や、反対にC++からJScriptの関数を実行する方法を紹介します。また、JScriptのArray
オブジェクトをC++で作成する方法についても紹介します。
対象読者
以下のアプリケーションを開発したことがある人。
- C++、JScriptを使ったアプリケーション
- Win32 APIを使ったアプリケーション
- COMコンポーネントを利用したアプリケーション
作成/実行環境
- Windows XP/Vista
- Visual Studio 2005
ソースコード
ダウンロードしたアーカイブには、プロジェクトが2つ収録されています。内容を表1に示します。
プロジェクト名 | 内容 |
call_jscript | JScriptからC++のクラスメソッドを呼び出す。 |
jscript_array | C++上でArrayオブジェクトを生成し、JScriptの関数を呼び出す。 |
JScriptを使うための準備
必要なヘッダーファイルとライブラリのリンク
必要なヘッダーファイルとライブラリをリンクするために、次のように「stdafx.h」を書き換えます。
#pragma once #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0501 #endif #pragma comment(lib,"user32.lib") #pragma comment(lib,"comsupp.lib") #pragma comment(lib,"ole32.lib") #include <tchar.h> #include <windows.h> #include <objbase.h> #include <comutil.h> #include <dispex.h> #include <activscp.h> #include "../ImplIUnknown.h" // 後述
COMの初期化と解放
Windows ScriptはCOMベースで実装されているので、COMの初期化と解放を実装します。
// (解放を簡単にするためのマクロを定義しておく) #define SAFE_RELEASE(p) {if(p){(p)->Release();(p)=NULL;}} int _tmain(int argc, _TCHAR* argv[]) { CoInitialize(NULL); //TODO : COM を使ったコードを書く CoUninitialize(); return 0; }
IUnknownの実装
JScriptを実行したり、JScriptから呼び出せるメソッドを実装したりするために、独自のCOMクラスを実装することになります。すべてのCOMクラスはIUnknown
インターフェースを実装しています。IUnknown
を容易に実装するためのマクロIMPL_IUNKNOWN
を「ImplIUnknown.h」に定義します。
#pragma once // インスタンスを作成 #define CO_CREATE(X,Y) X *Y=new X; // インスタンスを解放 #define SAFE_RELEASE(p) if((p)) { (p)->Release(); (p)=NULL; } // IUnknown インターフェイスの実装 // クラスのコンストラクタで refCount(1) として初期化すること。 #define IMPL_IUNKNOWN(IF_NAME) \ public:\ STDMETHODIMP_(ULONG) AddRef() {\ return ++refCount;\ }\ STDMETHODIMP_(ULONG) Release() {\ --refCount;\ if (refCount <= 0) {\ delete this;\ return 0;\ }\ return refCount;\ }\ STDMETHODIMP QueryInterface(const IID & riid,void **ppvObj) {\ if (!ppvObj)\ return E_POINTER;\ if (IsEqualIID(riid, __uuidof(IF_NAME)) ||\ IsEqualIID(riid, IID_IUnknown)) {\ AddRef();\ *ppvObj=this;\ return S_OK;\ }\ return E_NOINTERFACE;\ }\ private:\ ULONG refCount;
IMPL_IUNKNOWN
マクロは引数が1つあります。これには例えばIDispatch
のようなインターフェースの型を指定します。QueryInterface
にて指定したインターフェースの問い合わせがあると、this
ポインタを返し、戻り値はS_OK
となります。そうでない場合はE_NOINTERFACE
を返します。
インターフェースの型からインターフェースID(IID)への変換には__uuidof
を使っています。