修正了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() == 0) return 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 = -(-a + -123 * +5 + -a)
4 end function
翻译结果:
表达式:
1 function main()
2 integer a
3 a = -(-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) |
编辑 收藏