修正了return語句的一些Bug
添加了COM組件的支持(見Samples目錄下的factorial.txt)
ESEngine_Demo3.rar
posted @
2011-02-07 17:27 lwch 閱讀(1446) |
評論 (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 閱讀(2650) |
評論 (0) |
編輯 收藏
1.修正了函數調用時的一些Bug
2.示例中增加了一個遞歸求階乘的例子
ESEngine_Demo2.rar
posted @
2011-01-30 21:19 lwch 閱讀(1377) |
評論 (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 閱讀(1233) |
評論 (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 閱讀(1225) |
評論 (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 閱讀(2433) |
評論 (9) |
編輯 收藏
摘要: 本文的思路來源于http://m.shnenglu.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 閱讀(1637) |
評論 (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 閱讀(1477) |
評論 (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 閱讀(1661) |
評論 (0) |
編輯 收藏
按《自己動手寫操作系統》修改了代碼,并添加了任務0

源碼打包下載
posted @
2011-01-10 18:44 lwch 閱讀(1413) |
評論 (0) |
編輯 收藏
主要完成了鍵盤中斷和printf,printf_c,print_c等內核函數并刪除了一些無用的代碼
添加了編譯環境

源碼打包下載
接下來研究進程調度
posted @
2010-12-25 16:02 lwch 閱讀(1625) |
評論 (4) |
編輯 收藏

明天放出源碼..
posted @
2010-12-24 23:29 lwch 閱讀(465) |
評論 (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 閱讀(1992) |
評論 (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 閱讀(786) |
評論 (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 閱讀(1152) |
評論 (0) |
編輯 收藏