怎样编写自己的脚本解释程序

Rayman 2000-05-28 11:43:00
怎样编写一个自己的脚本解释程序?需要哪些知识?大概思路是什么?有没有可参考的例子?
请高手不吝赐教!
...全文
537 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
x86 2000-05-29
  • 打赏
  • 举报
回复
我给你发了一个,本来有三个步骤,我给你发的是最后一个步骤.
真的是很好的东西,不过需要又比较深的COM基础
用到了ActiveX Host,在MSDN中有帮助,
word和excel的VBS用的就是这种技术
下面是说明:

Hi All,

In this article will be described a way of implementing of an
ActiveX script host with MFC.

An ActiveX script host is an application that can run some code written
in other language (VBScript, VBA, Java script) and can expose the
application's internal COM to the script being runned.

The Micrososft's Internet Explorer, Excel, Word, Access - are
ActiveX script hosts. The first one use VBScript and the other ones
use VBA.

Most of the code concerning the idea how to implement a host
was taken from the "Axscript" example which is located on
your Developer Studio CD. The example was implemented with
WIN32 API. I have prepared three projects to describe the
implementation of an ActiveX script with MFC.

STEP1 - an example how to make your MFC program run VBScript code.
STEP2 - exposing internal automation objects to the VBScript engine.
STEP3 - adding ability to handle events fired in C++ code
by the VBScript code.

To see how the program works, compile the projects one after another
and run. Having run the program, select the menu item "VBScript->
Load script file". You will be proposed to select a file with
the script. Select the "TestProgram.txt" file which is located
in the directory of the project. Then select the "VBScript->Run"
menu item to run the script.

The first example would display a message box. The second one
would draw several rectangular sprites. The third one would
allow you to drag sprites with the mouse.

Note. If you make your project settings to place the results of
all the projects in the same folder, do not forget to use
the "Rebuild All" menu item when switching to another project.
Otherwise the program will not work properly.

To understand clearly how an ActiveX scripting engine works see
help in the Developer Studio. The information is available at
"Platform, SDK and DDK -> ActiveX SDK ->ActiveX scripting".


Step1.

To make your program run VBScript code (or other script) you have
to deal with the script engine which can be available through
IActiveScript and IActiveScriptParse interfaces. Also your
program must expose an object with IActiveScriptSite and optionaly
IActiveScriptSiteWindow interfaces.

The "Step1" example has the CMainFrame object which supports both
IActiveScript and IActiveScriptParse interfaces.

Most of the IActiveScript methods in this example were not implemented.
To understand how to implement OLE interfaces with MFC see the technical
note number 38.


Step2.

In this step there were two automation objects created with ClassWizard.
The first object is the CAXHostDoc was derived from CDocument. The second
one is the CAXSprite object was derived from CCmdTarget. CAXHostDoc has an
object called Animation which can manage sprites. CAXSprite is an OLE
wrapper for a rectangular sprite. Sprites can be added to the Animation
object, removed, moved, changed, ... but Animation does nothing until
you ask it to render an image to a particular DC. Do not care about how it
was implemented.

Your program can add to the scripting engine some top level item names,
which will be available in the script. This item names should be
associated with some COM objects in your application. Usualy i use the
"Application" object as top level item. But in this example, which is an SDI
application, the CAXHostApp object has a member m_pDoc to hold a pointer
to the document. In the CMainFrame::CreateScriptEngine method the
"Document" item name has been added to the script engine.

const TCHAR* szItemName=_T("Document");

USES_CONVERSION;
LPCOLESTR lpostrApp = T2COLE(szItemName);
hr=m_pIActiveScript->AddNamedItem(lpostrApp, SCRIPTITEM_ISVISIBLE);



The association between the item name added and the COM object is made
in the IActiveScriptSite::GetItemInfo method.

STDMETHODIMP CMainFrame::XScriptSite::GetItemInfo
(
LPCOLESTR pstrName,
DWORD dwReturnMask,
IUnknown** ppunkItemOut,
ITypeInfo** pptinfoOut
)
{
//HRESULT hr;
METHOD_PROLOGUE(CMainFrame, ScriptSite)

USES_CONVERSION;

LPCTSTR lpstrApplication=szItemName;

if (dwReturnMask & SCRIPTINFO_ITYPEINFO)
{
if (!pptinfoOut)
return E_INVALIDARG;
*pptinfoOut = NULL;
}

if (dwReturnMask & SCRIPTINFO_IUNKNOWN)
{
if (!ppunkItemOut)
return E_INVALIDARG;

*ppunkItemOut = NULL;

LPTSTR lpszName = OLE2T(pstrName);

//Look here, please /////////////
if(!_tcsicmp(lpstrApplication, lpszName))
{
*ppunkItemOut = theApp.m_pDoc->GetIDispatch(TRUE);
return S_OK;
////////////////////////////
}
}


return TYPE_E_ELEMENTNOTFOUND;
}

As soon as the association has been made, you can use the Documents
methods and properties. If there are some methods which return
interfaces to other COM objects in your application, you can
use their methods and properties without AddNamedItem function.
They are not top level objects. They was obtained from the Document
object (in this example there is just one such object - CAXSprite).


Step 3

In this example we make our program able to fire some events which
can be handled by the VBScript engine. First of all we will need to
provide ITypeInfo information to the script engine. The application
object has some members to hold this information (you can use global
variables).

ITypeLib* pITypeLib; //library AXHost
ITypeInfo* ptinfoClsDoc; //coclass Document
ITypeInfo* ptinfoIntDoc; //dispinterface IAXHost

ITypeInfo* ptinfoClsSprite; //coclass Sprite
ITypeInfo* ptinfoIntSprite; //dispinterface IAXSprite

To make your object fire events you need to create another interface
to your object's events. Modify your ODL file.

Example:

[uuid(B6032E41-636A-11d1-8F0B-F54176DCF130)]
dispinterface IAXHostEvents
{
properties:
methods: // Events
[id(1)] void OnMouseDown([in] short x, [in] short y);
[id(2)] void OnMouseMove([in] short x, [in] short y);
[id(3)] void OnMouseUp([in] short x, [in] short y);
[id(4)] void OnMouseDblClk([in] short x, [in] short y);
}

// Class information for CAXHostDoc

[ uuid(34E25943-6314-11D1-8F0B-F54176DCF130) ]
coclass Document
{
[default] dispinterface IAXHost;
[default, source] dispinterface IAXHostEvents;
};



In the CAXHostApp::InitInstance() method the type information was loaded

// ##### BEGIN ACTIVEX SCRIPTING SUPPORT #####
const TCHAR* lpstrTLB=_T("AXHost.tlb");
if(S_OK!=LoadTypeInfo(lpstrTLB,0,1,0,0,IID_LIBAXHost,IID_IAXHostClass,IID_IAXHost,FALSE,&pITypeLib,&ptinfoClsDoc,&ptinfoIntDoc))
return FALSE;

if(S_OK!=LoadTypeInfo(lpstrTLB,0,1,0,0,IID_LIBAXHost,IID_IAXSpriteClass,IID_IAXSprite,FALSE,&pITypeLib,&ptinfoClsSprite,&ptinfoIntSprite))
return FALSE;
// ##### END ACTIVEX SCRIPTING SUPPORT #####


In the MainFrm.module:

The AddNamedItem was called with the SCRIPTITEM_ISSOURCE flag.

pThis->m_pIActiveScript->AddNamedItem(lpszT, SCRIPTITEM_ISVISIBLE and SCRIPTITEM_ISSOURCE);


In the IActiveScriptSite::GetItemInfo ITypeInfo interface to the Document
CLASS object has been provided to the scripting engine.

STDMETHODIMP CMainFrame::XScriptSite::GetItemInfo
(
LPCOLESTR pstrName,
DWORD dwReturnMask,
IUnknown** ppunkItemOut,
ITypeInfo** pptinfoOut
)
{
//HRESULT hr;
METHOD_PROLOGUE(CMainFrame, ScriptSite)

USES_CONVERSION;

LPCTSTR lpstrApplication=szItemName;

if (dwReturnMask & SCRIPTINFO_ITYPEINFO)
{
if (!pptinfoOut)
return E_INVALIDARG;
*pptinfoOut = NULL;

//Attention, please
LPTSTR lpszName = OLE2T(pstrName);

if(!_tcsicmp(lpstrApplication, lpszName))
{
*pptinfoOut=theApp.ptinfoClsDoc;
return S_OK;
}
////////////////////
}

if (dwReturnMask & SCRIPTINFO_IUNKNOWN)
{
if (!ppunkItemOut)
return E_INVALIDARG;

*ppunkItemOut = NULL;

//Attention, please
LPTSTR lpszName = OLE2T(pstrName);

if(!_tcsicmp(lpstrApplication, lpszName))
{
*ppunkItemOut = theApp.m_pDoc->GetIDispatch(TRUE);
return S_OK;
}
///////////////////
}


return TYPE_E_ELEMENTNOTFOUND;
}


Also the IActiveScriptSite::RequestTypeLibs method was implemented.

//---------------------------------------------------------------------------
//
//---------------------------------------------------------------------------
STDMETHODIMP CMainFrame::XScriptSite::RequestTypeLibs(void)
{
METHOD_PROLOGUE(CMainFrame,ScriptSite);
HRESULT hr=pThis->m_pIActiveScript->AddTypeLib(IID_LIBAXHost, 1, 0, 0);
return hr;
}


If you want your object support events, it must support IConnectionPointContainer
interface and IProvideTypeInfo interface. See the article about
CConnectionPoint MFC object. See how it was implemented with the
CAXHostDoc object.


If you implement all the interfaces correctly, the scripting engine will
establish a connection to your object and you will be able to fire events
with help of a small function.

void CAXHostDoc::FireEvent(int iEvNum,VARIANTARG* pVar,int nParameters)
{
const CPtrArray* pConnections = m_xConnPt.GetConnections();
ASSERT(pConnections != NULL);

int cConnections = pConnections->GetSize();
IDispatch* pSink;
for (int i = 0; i < cConnections; i++)
{
pSink = (IDispatch*)(pConnections->GetAt(i));
ASSERT(pSink != NULL);
InvokeEvent(pSink, iEvNum, pVar, nParameters);
}
}

The iEvNum must be the same as in the ODL file. To fire the MouseDown
event, for instance, i have to use iEvNum to be equal 1. Because
[id(1)] void OnMouseDown([in] short x, [in] short y);

I should have made constants like IDEVENT_MOUSEDOWN and use them both
in the ODL file and in my C++ code.

Example:

void CAXHostView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
SetCapture();
VARIANTARG var[2];

VariantInit(&var[1]);
var[1].vt = VT_I2;
var[1].iVal = (short)point.x;
VariantInit(&var[0]);
var[0].vt = VT_I2;
var[0].iVal = (short)point.y;

GetDocument()->FireEvent(1,var,2);

CView::OnLButtonDown(nFlags, point);
}

Observe the sequence of passing parameters to the variant array.

I am not sure that in this small description i have written all
the tips to make your program work, but i send you the code which
you can investigate. And you should alse see the "Axscript" example
which does a little bit more. It provides a way how to make
subclassing with VBScript. See the BuildTypeInfo function in the
example to see how it has been done there.

If you have any questions, you can send me a message and i will try
to answer. But i must confess that i am a novice in COM. COM is
not difficult to understand but there are so many different objects
and interfaces. And one must know how to use them in one's programs.
The same can be said about the C++ language itself.

I also would like to get some examples on this matter if you have them.
For example, i don't know how to implement debugging features (they
say that Microsoft has already made a debugger fo VBScript), how
to interrupt a running script (i think i should create an another
thread and use an appropriate function), i tried to implement DUAL
interfaces to my objects but the VBScript used just the IDispatch
interfaces and i thought that VBScript did not support DUAL interfaces.

If you have any clues concerning this technology, please send them to
me. I would like also your opinion whether this feature is interesting,
for i can send some more examples. I mean not this sprites but a way
of using this technology in business applications. For example, my
program use special kinds of objects to work with SQL server databases
and Access databases such as "recordsets", "idsets, "caches", "reports",
"views" and others.

Kind regards.

kxy 2000-05-29
  • 打赏
  • 举报
回复
如果要写一个好的,要有编译原理的知识.类似解释执行的编译器如:
foxpro,basic,等等,我认为比较难.
Rayman 2000-05-29
  • 打赏
  • 举报
回复
多谢指点,虽然我还没有来得及看完这个程序,但我知道这就是我想要的东西,再次感谢!!!
Smile_Tiger 2000-05-29
  • 打赏
  • 举报
回复
你编写脚本解释器做什么用途??

一般来说,ini文件就是一个脚本,windows对它进行解释

首先你要定义脚本的基本格式,然后依据这个格式文档设计你的解释器
Apache JMeter应用程序是开源软件,是一个 100% 纯 Java 应用程序,它对被测系统(测试静态资源、动态资源、web应用程序等)进行负载测试、压力测试、容量测试等多种性能测试。Apache JMeter 功能包括:能够加载和性能测试许多不同的应用程序/服务器/协议类型:Web - HTTP, HTTPS (Java, NodeJS, PHP, ASP.NET, …)SOAP / REST WebservicesFTP文件传输协议Database via JDBCLDAPMessage-oriented middleware (MOM) via JMSMail - SMTP(S), POP3(S) and IMAP(S)Native commands or shell scriptsTCPJava Objects全功能测试IDE,允许快速测试计划记录(从浏览器或本机应用程序)、构建和调试;CLI 模式(命令行模式(以前​​称为非 GUI)/headless 模式)从任何Java兼容操作系统(Linux、Windows、Mac OSX 等)进行负载测试;一个完整且呈现的动态 HTML 报告;通过HTML、JSON、 XML、文本的响应格式中提取数据进行关联;完全可移植性和100%纯Java代码;完整多线程框架允许多个线程并发采样和不同线程组同时采样不同的函数;测试结果的缓存和离线分析/回放。高度可扩展的核心:可插拔采样器允许无限的测试能力脚本采样器(JSR223 兼容语言,如Groovy和 BeanShell)可以使用可插入计时器选择多个负载统计信息数据分析和可视化插件允许很大的可扩展性和个性化函数可用于为测试提供动态输入或提供数据操作通过适用于Maven、Gradle 和 Jenkins 的第三方开源库轻松持续集成。 本套课程内容:1.    JMeter概述2.    HTTPS协议简介3.    JMeter下载地址4.    JMeter软件安装5.    JMeter录制HTTPS协议步骤6.    Badboy录制脚本7.    手工编写脚本8.    项目实操:JMeter编写HTTPS协议脚本

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧