随笔-91  评论-137  文章-0  trackbacks-0
 
修正了return语句的一些Bug
添加了COM组件的支持(见Samples目录下的factorial.txt)

ESEngine_Demo3.rar
posted @ 2011-02-07 17:27 lwch 阅读(1430) | 评论 (0)编辑 收藏
1.首先我们必须知道C语言的调用约定为__cdecl(即参数从右向左依次进栈,由调用者还原堆栈).
2.一条push指令最多压入4个字节,当不足4个字节时应补齐4个字节,超过4个字节时应该由低位到高位依次压栈.
3.pop指令也和push一样一次只能弹出4个字节.
4.我们需要一个CallStruct类型来储存一个参数.
 1 class CallStruct
 2     {
 3     public:
 4         INT            Integer;
 5         BOOL        Bool;
 6         DOUBLE        Real;
 7         WCHAR        String[MAX_STRING];
 8         
 9         enum TYPE
10         {
11             ctInteger,
12             ctString,
13             ctBool,
14             ctReal,
15             ctVoid,
16         }Type;
17         
18         CallStruct() : Integer(0),Bool(FALSE),Real(0)
19         {
20             String[0]    = 0;
21         }
22 
23         CallStruct(const NAutoPtr<VirtualMachine::VarClass>& Var) : Integer(Var->Integer),Bool(Var->Bool),Real(Var->Real),Type((TYPE)Var->Type)
24         {
25             if(Type == ctString) wcscpy(String,Var->String);
26         }
27     };
5.我们需要一个列表来存放参数和一个返回值对象来存放返回值.
1     List<NAutoPtr<CallStruct>> VarList;
2     NAutoPtr<CallStruct> Return;
6.最后我们需要一个HMODULE和一个FARPROC分别存放dll的句柄和函数地址.
1     HMODULE hModule;
2     FARPROC FunctionPtr;
7.然后我们添加几个功能函数.
1     BOOL AddVar(NAutoPtr<VirtualMachine::VarClass>& Var);
2     BOOL SetReturnType(CallStruct::TYPE Type);
3     BOOL SetLibName(LPTSTR Name);
4     BOOL SetFunctionName(LPTSTR Name);
注意:GetProcAddress第二个参数只接受LPCSTR类型的字符串,应此如果传入的是Unicode编码的字符必须将其转换成ANSI的.
8.我们添加一个函数Run用于调用函数.
 1 BOOL CallMacro::Run()
 2 {
 3     if(FunctionPtr == 0 || Return.Buffer() == 0return FALSE;
 4     union RealStruct
 5     {
 6         double Real;
 7         struct
 8         {
 9             int Head,Tail;
10         };
11     };
12     NAutoPtr<CallStruct> cs;
13     int Integer;
14     BOOL Bool;
15     RealStruct Real; // Push指令一次只能压入4字节
16     LPTSTR String;
17 
18     int iEsp;
19     __asm mov int ptr[iEsp],esp; // 保存esp
20     for(int i=0;i<VarList.Size();i++)
21     {
22         cs = VarList[i];
23         Integer = cs->Integer;
24         Bool = cs->Bool;
25         Real.Real = cs->Real;
26         String = cs->String;
27         switch(cs->Type)
28         {
29         case CallStruct::ctInteger:
30             __asm push Integer;
31             break;
32         case CallStruct::ctString:
33             __asm push String;
34             break;
35         case CallStruct::ctBool:
36             __asm push Bool;
37             break;
38         case CallStruct::ctReal:
39             __asm push Real.Tail;
40             __asm push Real.Head;
41             break;
42         }
43     }
44     FARPROC proc = FunctionPtr;
45     int Head,Tail;
46     __asm
47     {
48         call proc
49         mov int ptr[Head],edx
50         mov int ptr[Tail],eax
51     }
52     switch(Return->Type)
53     {
54     case CallStruct::ctInteger:
55         Return->Integer = Tail;
56         break;
57     case CallStruct::ctString:
58         wcscpy(Return->String,(LPCTSTR)Tail);
59         break;
60     case CallStruct::ctBool:
61         Return->Bool = Tail;
62         break;
63     case CallStruct::ctReal:
64         __asm fstp [Real.Real];
65         Return->Real = Real.Real;
66         break;
67     }
68     // __declspec调用约定,需要手工还原堆栈
69     __asm mov esp,int ptr[iEsp];
70     return TRUE;
71 }
Run函数首先检查是否已经装载了DLL并获得了函数地址,以及返回值类型是否已经定义.
然后根据类型依次将函数压栈.
然后调用call指令并保存返回值.(这里需要注意的是当返回值类型为double或float类型时必须使用fstp指令从FPU寄存器栈的栈顶的值取出来)
最后还原堆栈.

然后我们来测试一下.
创建一个名为TestDLL的DLL工程并添加函数Test.
1 TESTDLL_API double Test(double d,double* d1,WCHAR* lpBuffer)
2 {
3     if(d == 123.456789) MessageBox(0,lpBuffer,L"",0);
4     *d1 = 789.654;
5     return 77777;
6 }

然后创建一个测试工程,添加相关文件.
在_tmain中添加以下代码.
 1 int _tmain(int argc, _TCHAR* argv[])
 2 {
 3     double d;
 4     CallMacro cm;
 5     NAutoPtr<VirtualMachine::VarClass> Var;
 6 
 7     Var = new VirtualMachine::VarClass;
 8     Var->Type = VirtualMachine::VarClass::vtString;
 9     wcscpy(Var->String,L"aaaaa");
10     cm.AddVar(Var);
11 
12     Var = new VirtualMachine::VarClass;
13     Var->Type = VirtualMachine::VarClass::vtInteger;
14     Var->Integer = (INT)&d;
15     cm.AddVar(Var);
16 
17     Var = new VirtualMachine::VarClass;
18     Var->Type = VirtualMachine::VarClass::vtReal;
19     Var->Real = 123.456789;
20     cm.AddVar(Var);
21 
22     cm.SetLibName(L"TestDll.dll");
23     cm.SetFunctionName(L"Test");
24     cm.SetReturnType(CallMacro::CallStruct::ctReal);
25     cm.Run();
26 
27     wprintf(L"%f %f\n",d,cm.Return->Real);
28     system("pause");
29     return 0;
30 }

编译并运行,可以看到Test函数调用成功,并成功输出d的值和返回值.

最后给出完整代码.
posted @ 2011-02-06 22:21 lwch 阅读(2579) | 评论 (0)编辑 收藏
1.修正了函数调用时的一些Bug
2.示例中增加了一个递归求阶乘的例子

ESEngine_Demo2.rar
posted @ 2011-01-30 21:19 lwch 阅读(1345) | 评论 (0)编辑 收藏

运行方法:
1.打开命令行提示符
2.cd ESEngine.exe所在路径
3.ESEngine xxx.txt

1.Samples文件夹下有几个例子
2.函数目前只写了
  "function" "{Symbol}" "{LQ}" "{RQ}" stmt_list "end" "function"
  "function" "{Symbol}" "{LQ}" "{RQ}" "end" "function"
  "function" "{Symbol}" "{LQ}" paramter_list "{RQ}" "as" var_type stmt_list "end" "function"
  这三类,所以对于
  function mn(integer s)
 stmts
  end function
  在生成语法树时会产生错误

ESEngine_Demo1_0.rar

posted @ 2011-01-28 21:03 lwch 阅读(1212) | 评论 (0)编辑 收藏
表达式:
1 function main()
2     integer a
3     a = -(-+ -123 * +5 + -a)
4 end function

翻译结果:


表达式:
1 function main()
2     integer a
3     a = -(-- -1)
4 end function

翻译结果:
posted @ 2011-01-27 21:39 lwch 阅读(1211) | 评论 (1)编辑 收藏
《面向组合子的一些测试》 进一步完善代码,制作出词法分析器.

我们首先需要一个Fail基类,他有一个纯虚函数Parser.
1 class Fail
2 {
3 public:
4     virtual NWString Parser(NWString& input)=0;
5 };
Parser的输入为要分析的字符串,输出为分析完成后剩余的字符串.

然后我们需要一个Ch和一个Str分别用来分析单个字符和一个字符串.
 1 class Ch : public Fail
 2 {
 3 public:
 4     Ch(WCHAR _value) : value(_value){}
 5 
 6     NWString Parser(NWString& input);
 7 
 8     WCHAR Value();
 9 protected:
10     WCHAR value; // 待匹配串
11 };
12 
13 class Str : public Fail
14 {
15 public:
16     Str(NWString _value) : value(_value){}
17 
18     NWString Parser(NWString& input);
19 protected:
20     NWString value; // 待匹配串
21 };

然后是Seq,Alt和Any,分别表示组合,选择和循环.
 1 class Seq : public Fail
 2 {
 3 public:
 4     Seq(const NAutoPtr<Fail>& _left,const NAutoPtr<Fail>& _right) : left(_left),right(_right){}
 5 
 6     NWString Parser(NWString& input);
 7 protected:
 8     NAutoPtr<Fail> left;
 9     NAutoPtr<Fail> right;
10 };
11 
12 class Alt : public Fail
13 {
14 public:
15     Alt(const NAutoPtr<Fail>& _left,const NAutoPtr<Fail>& _right) : left(_left),right(_right){}
16 
17     NWString Parser(NWString& input);
18 protected:
19     NAutoPtr<Fail> left;
20     NAutoPtr<Fail> right;
21 };
22 
23 class Any : public Fail
24 {
25 public:
26     Any(const NAutoPtr<Fail>& _left,const int _count) : left(_left),count(_count){}
27 
28     NWString Parser(NWString& input);
29 protected:
30     NAutoPtr<Fail> left;
31     int count;
32 };

最后我们需要一个Node类型来存放以上这几类对象.
 1 class Node
 2 {
 3 public:
 4     Node(){}
 5     Node(const NAutoPtr<Fail>& _left) : left(_left){}
 6 
 7     friend NAutoPtr<Node> operator+(const NAutoPtr<Node>& left,const NAutoPtr<Node>& right);
 8     friend NAutoPtr<Node> operator|(const NAutoPtr<Node>& left,const NAutoPtr<Node>& right);
 9     friend NAutoPtr<Node> operator-(const NAutoPtr<Node>& left,const NAutoPtr<Node>& right);
10 
11     static NAutoPtr<Node> OnceMore(NAutoPtr<Node> node);
12     static NAutoPtr<Node> More(NAutoPtr<Node> node);
13     static NAutoPtr<Node> NewCh(WCHAR input);
14     static NAutoPtr<Node> NewStr(NWString input);
15 
16     NWString Parser(NWString& input);
17 
18     NAutoPtr<Fail>& Value();
19 protected:
20     NAutoPtr<Fail> left;
21 };
下面来分析一下Node里的函数:
+:对应于Seq,用于将两个Node连接起来.
|:对应与Alt,用于选择两个Node.
-:只有left和right的Value()都是NAutoPtr<Ch>时才可使用,内部有类型转换,表示从哪个字符到哪个字符.
OnceMore:重复1次及以上.
More:重复0次以上.
NewCh:生成一个NAutoPtr<Ch>的Node对象.
NewStr:生成一个NAutoPtr<Str>的Node对象.

下面我们需要4个宏.
1 #define ONCEMORE(N)                    Node::OnceMore(N)
2 #define MORE(N)                        Node::More(N)
3 #define NEWCH(N)                    Node::NewCh(N)
4 #define NEWSTR(N)                    Node::NewStr(N)
这4个宏仅为了输入方便

然后我们来测试一下:
1     NAutoPtr<Node> Symbol = ONCEMORE(NEWCH('_'| NEWCH('a'- NEWCH('z')) | (NEWCH('A'- NEWCH('Z'))
2         + MORE(NEWCH('_'| (NEWCH('0'- NEWCH('9')) | (NEWCH('a'- NEWCH('z')) | (NEWCH('A'- NEWCH('Z')));
3     NAutoPtr<Node> Number = ONCEMORE(NEWCH('0'- NEWCH('9'));
4     NAutoPtr<Node> Real = Number + NEWCH('.'+ Number;
相信对正则表达式有一定认识的同学已经知道这3条语句分别对应于什么正则表达式.
Symbol->[_a-zA-Z]+[_0-9a-zA-Z]*
Number->[0-9]+
Real->[0-9]+.[0-9]+

定义一个待分析的字符串.
1     NWString str = L"abcce_fg123.459agetr";

对其分析.
1     wprintf(L"%s\n",str);
2     wprintf(L"%s\n",Symbol->Parser(str));
3     wprintf(L"%s\n",Real->Parser(str));
4     wprintf(L"%s\n",Symbol->Parser(str));

分析结果.
1 abcce_fg123.459agetr
2 123.459agetr
3 agetr
4 

因为没有考虑分析效率问题,所以使用NWString作为输入和输出,在实际使用中可用LPTSTR来代替NWString,同时修改响应代码.
最后给出源代码
posted @ 2011-01-26 22:11 lwch 阅读(2393) | 评论 (9)编辑 收藏
     摘要: 本文的思路来源于http://www.cppblog.com/vczh/archive/2008/05/21/50656.html首先先看代码:   1 #include <stdio.h>  2   3 class Element  4 {&n...  阅读全文
posted @ 2011-01-22 17:11 lwch 阅读(1609) | 评论 (4)编辑 收藏
下面来分析一下NScript的部分数据结构
 1     class SyntaxNode
 2     {
 3     public:
 4         int Op1;
 5         int Op2;
 6         List<NAutoPtr<SyntaxNode>> Child;
 7 
 8         SyntaxNode(int O1,int O2) : Op1(O1),Op2(O2){}
 9     };
10 
11     class CharClass
12     {
13     public:
14         int Index;
15         NWString String;
16 
17         CharClass(NWString S) : String(S){}
18     };

每个语法树的节点有2个参数Op1,Op2分别表示当前节点的类型和附加参数
Child为当前节点的子节点

CharClass结构则比较简单分别为索引和字符

然后是部分SyntaxNode的Op1的枚举:
1     enum OpCode_Type
2     {
3         opNull,
4         opVar,
5         opConst,
6     };

以及VarType的枚举:
 1     enum Var_Type
 2     {
 3         vtNull,
 4         vtVoid,
 5         vtBool,
 6         vtInt,
 7         vtReal,
 8         vtString,
 9         vtSymbol,
10     };
和产生式索引的宏定义:
 1     #define INDEX_VARTYPE_VOID                1
 2     #define INDEX_VARTYPE_BOOL                2
 3     #define INDEX_VARTYPE_INT                3
 4     #define INDEX_VARTYPE_REAL                4
 5     #define INDEX_VARTYPE_STRING            5
 6     #define INDEX_VALUETYPE_STRING            6
 7     #define INDEX_VALUETYPE_SYMBOL            7
 8     #define INDEX_VALUETYPE_REAL            8
 9     #define INDEX_VALUETYPE_DIGIT            9
10     #define INDEX_VALUETYPE_TRUE            10
11     #define INDEX_VALUETYPE_FALSE            11

以上索引的定义取自NS.txt,随着以后文法的增加这里的索引定义也会增加
NS.h,NS.cpp,NS.ParserTable均是由NScriptMacro.exe运行NS.txt生成的

下面来看一下SyntaxAnalyze函数:
 1 BOOL NSyntax::SyntaxAnalyze(int i)
 2 {
 3     BOOL bResult = TRUE;
 4     // 根据产生式索引生成语法树
 5     switch(i)
 6     {
 7     case INDEX_VARTYPE_VOID:
 8     case INDEX_VARTYPE_BOOL:
 9     case INDEX_VARTYPE_INT:
10     case INDEX_VARTYPE_REAL:
11     case INDEX_VARTYPE_STRING:
12         bResult = VarType(i);
13         break;
14     case INDEX_VALUETYPE_STRING:
15     case INDEX_VALUETYPE_SYMBOL:
16     case INDEX_VALUETYPE_REAL:
17     case INDEX_VALUETYPE_DIGIT:
18     case INDEX_VALUETYPE_TRUE:
19     case INDEX_VALUETYPE_FALSE:
20         bResult = ValueType(i);
21         break;
22     }
23     return bResult;
24 }

这个函数根据传入参数(产生式索引)调用相关函数生成语法树,具体语法树的生成过程请看相关代码
posted @ 2011-01-14 16:00 lwch 阅读(1452) | 评论 (0)编辑 收藏
项目地址

最初文法定义为:
 1 %token "void" "bool" "int" "real" "string";
 2 %token "true" "false";
 3 %token "{" "}" "," ";" "=";
 4 %token "+" "-" "*" "/";
 5 %token ">" "<" ">=" "<=" "==" "and" "not" "or";
 6 
 7 %start program;
 8 
 9 var_type    ->    "void"
10             |    "bool"
11             |    "int"
12             |    "real"
13             |    "string"
14             ;
15 
16 value_type    ->    "{String}"
17             |    "{Symbol}"
18             |    "{real}"
19             |    "{digit}"
20             |    "true"
21             |    "false"
22             ;
23 
24 paramter_define_desc    ->    "{LQ}" paramter_defines "{RQ}"
25                         |    "{LQ}" "{RQ}"
26                         ;
27 
28 paramter_defines    ->    paramter_defines "," paramter_one
29                     |    paramter_one
30                     ;
31 
32 paramter_one        ->    var_type "{Symbol}"
33                     ;
34 
35 assign_type            ->    "{Symbol}"
36                     ;
37 
38 program        ->    item_list
39             ;
40 
41 item_list    ->    item_list item
42             |    item
43             ;
44 
45 item        ->    function
46             |    define_desc ";"
47             ;
48 
49 stmt_list    ->    stmt_list stmt
50             |    stmt
51             ;
52 
53 stmt        ->    define_desc ";"
54             |    assign_desc ";"
55             |    ";"
56             ;
57 
58 function    ->    var_type "{Symbol}" paramter_define_desc "{" stmt_list "}"
59             |    var_type "{Symbol}" paramter_define_desc "{" "}"
60             ;
61 
62 define_desc    ->    define_desc "," "{Symbol}"
63             |    var_type "{Symbol}"
64             ;
65 
66 assign_desc    ->    assign_type "=" exp
67             ;
68 
69 exp        ->    exp ">" exp1
70         |    exp "<" exp1
71         |    exp ">=" exp1
72         |    exp "<=" exp1
73         |    exp "==" exp1
74         |    exp "and" exp1
75         |    exp "or" exp1
76         |    "not" exp1
77         |    "+" exp1
78         |    "-" exp1
79         |    exp1
80         ;
81 
82 exp1        ->    exp1 "+" exp2
83         |    exp1 "-" exp2
84         |    exp2
85         ;
86 
87 exp2        ->    exp2 "*" exp3
88         |    exp2 "/" exp3
89         |    exp3
90         ;
91 
92 exp3        ->    "{LQ}" exp "{RQ}"
93         |    value_type
94         ;

由以上文法中仅有函数的定义和变量的定义
有点类C的味道.
已成功将ESLanguage大部分代码移植到这个项目里.
posted @ 2011-01-13 21:38 lwch 阅读(1643) | 评论 (0)编辑 收藏
按《自己动手写操作系统》修改了代码,并添加了任务0


源码打包下载
posted @ 2011-01-10 18:44 lwch 阅读(1399) | 评论 (0)编辑 收藏
主要完成了键盘中断和printf,printf_c,print_c等内核函数并删除了一些无用的代码
添加了编译环境


源码打包下载
接下来研究进程调度
posted @ 2010-12-25 16:02 lwch 阅读(1610) | 评论 (4)编辑 收藏

明天放出源码..
posted @ 2010-12-24 23:29 lwch 阅读(452) | 评论 (0)编辑 收藏

首先修改task1的代码使其运行一次后进入无限循环
将jmp _task1修改为jmp $
将timer_interrupt修改为:

 1 _timer_interrupt:
 2     PUSH ds
 3     PUSH edx
 4     PUSH ecx
 5     PUSH ebx
 6     PUSH eax
 7     ;MOV eax,0x10
 8     ;MOV dx,ax
 9     in al,0x21            ; ┓
10     or al,(1 << 1)    ; ┣ 屏蔽当前中断
11     out 0x21,al            ; ┛
12     mov al,0x20            ; ┓置EOI位,其后8259A才能相应新的中断
13     out 0x20,al            ; ┛
14     sti                            ; 允许响应新中断
15     in al,0x60            ; 从0x60端口读出扫描码
16     ;MOV eax,1
17     ;cmp DWORD [current],eax
18     ;je y1
19     ;MOV DWORD [current],eax
20     ;JMP TSS1_SEL : 0
21     ;jmp y2
22 y1:
23     ;MOV DWORD [current],0
24     ;JMP TSS0_SEL : 0
25     ;MOV eax,0x17
26     ;MOV ds,ax
27     ;MOV al,65
28     call write_char    ; 这里仅简单的将扫描码作为ANSI码打印出来
29     ;MOV ecx,0xfff
30 y2:
31     cli
32     in al,0x21                ; ┓
33     and al,~(1 << 1)    ; ┣ 恢复接受当前中断
34     out 0x21,al                ; ┛
35     POP eax
36     POP ebx
37     POP ecx
38     POP edx
39     POP ds
40     IRET

注:因为键盘中断处理过程运行于Ring0,应此可以直接调用内核函数write_char
然后修改IDT表的0x21(0x21对应于IRQ1,表示键盘中断)项的offset_l和offset_h使其指向timer_interrupt中断处理过程.
 1 void init_idt()
 2 {
 3     int i;
 4     for(i=0;i<256;i++)
 5     {
 6         if(0x21 == i || 0x80 == i)
 7         {
 8             continue;
 9         }
10         setup_int_gate((dword)ignore_int,i);        
11     }
12     //setup_int_gate((dword)timer_interrupt,0x20);
13     setup_int_gate((dword)timer_interrupt,0x21);
14     setup_trap_gate((dword)system_interrupt,0x80);    
15     
16     idtr[0= 8 * 256;
17     idtr[1= ((dword)&idt_[0+ KERNEL_BASE) & 0xffff;
18     idtr[2= ((dword)&idt_[0+ KERNEL_BASE)>>16;
19 }

最后启动键盘中断,将8259A主片的IRQ0位设为1,IRQ1位设为0
1     MOV edx,0x21
2     in al,dx
3     AND al,0xFD
4     OUT dx,al
注:0xFD对应二进制码11111101
调试结果:

按下a键输出一个字符,弹起a键输出另一个字符
由于直接将扫描码作为ANSI码输出因此会出现两个乱码字符

完整代码打包下载
posted @ 2010-12-11 17:46 lwch 阅读(1971) | 评论 (5)编辑 收藏
COM.h:
 1 #pragma once
 2 #include <atlcomcli.h>
 3 
 4 class COMMacro
 5 {
 6 public:
 7     COMMacro(LPTSTR Object);
 8     ~COMMacro();
 9     BOOL Invoke(LPTSTR strFunction,VARIANT* pVarParams,int nParamterCount,VARIANT* pResult);
10     VARIANT ToVARIANT(BSTR str);
11     VARIANT ToVARIANT(int nVal);
12     VARIANT ToVARIANT(bool bVal);
13     VARIANT ToVARIANT(double dVal);
14     VARIANT ToVARIANT_ByRef(BSTR* pStr);
15     VARIANT ToVARIANT_ByRef(int* pnVal);
16     VARIANT ToVARIANT_ByRef(bool* pbVal);
17     VARIANT ToVARIANT_ByRef(double* pdVal);
18     BSTR ToBSTR(VARIANT Val);
19     int ToInt(VARIANT Val);
20     bool ToBool(VARIANT Val);
21     double ToDouble(VARIANT Val);
22 
23     BOOL ToBSTR(LPTSTR src,BSTR& dest);
24 protected:
25     CLSID m_clsID;
26     CComPtr<IUnknown> m_Unknown;
27     CComDispatchDriver* m_pDispatchDriver;
28 };
COM.cpp:
  1 #include "stdafx.h"
  2 #include "COM.h"
  3 #include <comdef.h>
  4 
  5 COMMacro::COMMacro(LPTSTR Object)
  6 {
  7     HRESULT hr = CLSIDFromProgID(Object,&m_clsID);
  8     if(FAILED(hr))
  9     {
 10         throw _com_error(hr);
 11         return;
 12     }
 13     hr = CoCreateInstance(m_clsID,NULL,CLSCTX_ALL,IID_IUnknown,(LPVOID*)&m_Unknown);
 14     if(FAILED(hr))
 15     {
 16         throw _com_error(hr);
 17         return;
 18     }
 19     m_pDispatchDriver = new CComDispatchDriver(m_Unknown);
 20 }
 21 
 22 COMMacro::~COMMacro()
 23 {
 24     delete m_pDispatchDriver;
 25 }
 26 
 27 BOOL COMMacro::Invoke(LPTSTR strFunction,VARIANT* pVarParams,int nParamterCount,VARIANT* pResult)
 28 {
 29     DISPID DispID;
 30     HRESULT hr = m_pDispatchDriver->GetIDOfName(strFunction,&DispID);
 31     if(FAILED(hr))
 32     {
 33         throw _com_error(hr);
 34         return FALSE;
 35     }
 36     hr = m_pDispatchDriver->InvokeN(DispID,pVarParams,nParamterCount,pResult);
 37     if(FAILED(hr))
 38     {
 39         throw _com_error(hr);
 40         return FALSE;
 41     }
 42     return TRUE;
 43 }
 44 
 45 VARIANT COMMacro::ToVARIANT(BSTR str)
 46 {
 47     VARIANT vResult;
 48     vResult.vt = VT_BSTR;
 49     vResult.bstrVal = SysAllocString(str);
 50     return vResult;
 51 }
 52 
 53 VARIANT COMMacro::ToVARIANT(int nVal)
 54 {
 55     VARIANT vResult;
 56     vResult.vt = VT_I4;
 57     vResult.intVal = nVal;
 58     return vResult;
 59 }
 60 
 61 VARIANT COMMacro::ToVARIANT(bool bVal)
 62 {
 63     VARIANT vResult;
 64     vResult.vt = VT_BOOL;
 65     vResult.boolVal = bVal;
 66     return vResult;
 67 }
 68 
 69 VARIANT COMMacro::ToVARIANT(double dVal)
 70 {
 71     VARIANT vResult;
 72     vResult.vt = VT_R8;
 73     vResult.dblVal = dVal;
 74     return vResult;
 75 }
 76 
 77 VARIANT COMMacro::ToVARIANT_ByRef(BSTR* pStr)
 78 {
 79     VARIANT vResult;
 80     vResult.vt = VT_BSTR | VT_BYREF;
 81     vResult.byref = pStr;
 82     return vResult;
 83 }
 84 
 85 VARIANT COMMacro::ToVARIANT_ByRef(int* pnVal)
 86 {
 87     VARIANT vResult;
 88     vResult.vt = VT_I4 | VT_BYREF;
 89     vResult.byref = pnVal;
 90     return vResult;
 91 }
 92 
 93 VARIANT COMMacro::ToVARIANT_ByRef(bool* pbVal)
 94 {
 95     VARIANT vResult;
 96     vResult.vt = VT_BOOL | VT_BYREF;
 97     vResult.byref = pbVal;
 98     return vResult;
 99 }
100 
101 VARIANT COMMacro::ToVARIANT_ByRef(double* pdVal)
102 {
103     VARIANT vResult;
104     vResult.vt = VT_BOOL | VT_BYREF;
105     vResult.byref = pdVal;
106     return vResult;
107 }
108 
109 BSTR COMMacro::ToBSTR(VARIANT Val)
110 {
111     return *(BSTR*)Val.byref;
112 }
113 
114 int COMMacro::ToInt(VARIANT Val)
115 {
116     return *(int*)Val.byref;
117 }
118 
119 bool COMMacro::ToBool(VARIANT Val)
120 {
121     return *(bool*)Val.byref;
122 }
123 
124 double COMMacro::ToDouble(VARIANT Val)
125 {
126     return *(double*)Val.byref;
127 }
128 
129 BOOL COMMacro::ToBSTR(LPTSTR src,BSTR& dest)
130 {
131     dest = SysAllocString(src);
132     return TRUE;
133 }

使用说明:
1.构造函数:
参数(字符串常量):工程名.类名
2.Invoke:
参数1(字符串常量):函数名
参数2(VARIANT数组):调用参数,从右至左
参数3(数值常量):调用参数个数
参数4(VARIANT指针):返回值
3.ToVARIANT:将给定参数转换为VARIANT类型
4.ToVARIANT_ByRef:将给定参数转换为ByRef的VARIANT类型
5.ToBSTR:将给定ByRef的VARIANT转换为BSTR
6.ToInt:将给定ByRef的VARIANT转换为int
7.ToBool:将给定ByRef的VARIANT转换为bool
8.ToDouble:将给定ByRef的VARIANT转换为double
9.ToBSTR:将给定字符串常量转换为BSTR类型

示例:
 1     CoInitialize(0); // 初始化ATL
 2     try
 3     {
 4         COMMacro m(L"aaa.bbb");
 5         VARIANT vResult,vParams[3];
 6         int i = 100;
 7         BSTR str;
 8         m.ToBSTR(L"abc",str);
 9         vParams[2= m.ToVARIANT(123.456);
10         vParams[1= m.ToVARIANT(i);
11         vParams[0= m.ToVARIANT_ByRef(&str);
12         m.Invoke(L"aaa",vParams,3,&vResult);
13         wprintf(L"%s\n",m.ToBSTR(vParams[0]));
14     }
15     catch(_com_error& e)
16     {
17         wprintf(L"%s\n",e.ErrorMessage());
18     }
posted @ 2010-11-20 22:40 lwch 阅读(755) | 评论 (0)编辑 收藏
代码:
 1 function fact(integer n) as integer
 2     if n > 1 then
 3         return fact(n - 1* n
 4     else
 5         return n
 6     end if
 7 end function
 8 
 9 function main()
10     integer Result
11     Result = fact(5)
12 end function
符号表:
 0    n
 
1    1
 
2    fact
 
3    Result
 
4    5
 
5    main
翻译结果:
 
posted @ 2010-10-02 11:56 lwch 阅读(1140) | 评论 (0)编辑 收藏
仅列出标题
共7页: 1 2 3 4 5 6 7