Feeds:
文章
留言

Archive for 八月 8th, 2007

C++ 使用 JScript 和 VBScript

Live SpaceGoogle DocGoogle Blog
Chui-Wen Chiu
2007.08.08

測試環境
1. Windows XP Pro SP2
2. Visual Studio 2005

範例程式下載

一般 C++ 會使用 Python  作為 Script 引擎,但本文將說明透過 Windows 內建的 Script 引擎,讓 C++ 可以使用 VBScript 或 JScript 引擎。一切的核心是由 Microsoft Scripting ActiveX (MSSCR.OCX)元件所提供,由於是 COM 元件,所以,其他支援 COM 的語言也可透過類似的方法達到。

以下是 C++ 使用 JScript 的簡單範例

#import "msscript.ocx" no_namespace
#include <comutil.h>
#include <tchar.h>

const TCHAR JSCRIPT[]        = _T("JScript");
const int LANGUAGE_NAME_LEN    = 40;

int main(int argc, _TCHAR* argv[]){
    CoInitialize(NULL);

    // 建立 COM 元件
    IScriptControlPtr m_pScript;   
    HRESULT hr = m_pScript.CreateInstance(__uuidof(ScriptControl));
    _com_util::CheckError( hr );

    // 設定 Script Engine
    TCHAR    m_szLanguage[LANGUAGE_NAME_LEN+1];   
    _tcscpy(m_szLanguage, JSCRIPT);
    m_pScript->PutAllowUI( VARIANT_FALSE );   
    m_pScript->PutLanguage( _bstr_t(m_szLanguage ) );

    // 宣告一個新函數
    _bstr_t strCode = _T("function calc(a, b){ return a+b; }");
    m_pScript->AddCode( strCode );

    // 參數設定
    SAFEARRAY* saParameters;
    saParameters = SafeArrayCreateVector(VT_VARIANT, 0, 2);
    _variant_t var;   

    long lIndices = 0;
    var = 33;
    SafeArrayPutElement(saParameters, &lIndices, (void*)&var);   

    lIndices = 1;
    var = 44;
    SafeArrayPutElement(saParameters, &lIndices, (void*)&var);   

    // 呼叫函數 calc(33, 44) = 77
    VARIANT varRet = m_pScript->Run("calc", &saParameters);
    LPCTSTR result = (LPCTSTR)_bstr_t(varRet);

    // 顯示結果
    MessageBox(0, result, _T("Result"), 0);

    m_pScript = NULL;

    CoUninitialize();
    return 0;
}

只要將上述程式稍作修改,即可改用 VBScript 引擎

#import "msscript.ocx" no_namespace
#include <comutil.h>
#include <tchar.h>

const TCHAR VBSCRIPT[]        = _T("VBScript");
const int LANGUAGE_NAME_LEN    = 40;

int main(int argc, _TCHAR* argv[]){
    CoInitialize(NULL);

    // 建立 COM 元件
    IScriptControlPtr m_pScript;   
    HRESULT hr = m_pScript.CreateInstance(__uuidof(ScriptControl));
    _com_util::CheckError( hr );

    // 設定 Script Engine
    TCHAR    m_szLanguage[LANGUAGE_NAME_LEN+1];   
    _tcscpy(m_szLanguage, VBSCRIPT);
    m_pScript->PutAllowUI( VARIANT_FALSE );   
    m_pScript->PutLanguage( _bstr_t(m_szLanguage ) );

    // 宣告一個新函數
    _bstr_t strCode = _T("Function calc(a,b) calc = CInt(a)+CInt(b) End Function");
    m_pScript->AddCode( strCode );

    // 參數設定
    SAFEARRAY* saParameters;
    saParameters = SafeArrayCreateVector(VT_VARIANT, 0, 2);
    _variant_t var;   

    long lIndices = 0;
    var = 33;
    SafeArrayPutElement(saParameters, &lIndices, (void*)&var);   

    lIndices = 1;
    var = 44;
    SafeArrayPutElement(saParameters, &lIndices, (void*)&var);   

    // 呼叫函數 calc(33, 44) = 77
    VARIANT varRet = m_pScript->Run("calc", &saParameters);
    LPCTSTR result = (LPCTSTR)_bstr_t(varRet);

    // 顯示結果
    MessageBox(0, result, _T("Result"), 0);

    m_pScript = NULL;

    CoUninitialize();
    return 0;
}

上述的片段用來了解 Script 引擎是相當好,可是實務上太過於瑣碎不容易維護。所以,[1] 提供兩個好用輔助類別:CScriptObject 和 CSafeArrayHelper。下面使用這兩個類別改寫上述 JScript 的範例。

#include <tchar.h>
#include <windows.h>

#include "ScriptObject.h"
#include "SafeArrayHelper.h"

int main(int argc, _TCHAR* argv[]){
    CoInitialize(NULL);

    CScriptObject*    m_ScriptObj = new CScriptObject();

    // 設定 Script Engine
    m_ScriptObj->SetLanguage( _T("JScript") );

    // 宣告一個新函數
    m_ScriptObj->AddScript( _T("function calc(a, b){ return a+b; }") );

    // 參數設定
    CSafeArrayHelper sfHelper;
    _variant_t var;
    sfHelper.Create(VT_VARIANT, 1, 0, 2);   
    var = 33;
    sfHelper.PutElement(0, (void*)&var);   

    var = 44;
    sfHelper.PutElement(1, (void*)&var);   

    LPSAFEARRAY sa =  sfHelper.GetArray();
    _variant_t varRet;

    // 呼叫函數
    m_ScriptObj->RunProcedure(_T("calc"), &sa, &varRet);
    LPCTSTR result = (LPCTSTR)_bstr_t(varRet);

    // 顯示結果
    MessageBox(0, result, _T("Result"), 0);

    delete m_ScriptObj;

    CoUninitialize();
}

上述三個範例的執行結果都是如下:

參考資料
[1] Ernest Laurentin, "Adding VBScript and JScript support in your C++ applications"

Read Full Post »