根據之前的計劃,讓
Vczh Library++3.0的編譯器變成語言的公共后端的同時,開放幾乎所有層的API讓人們可以從各種基礎上開發自己的DSL,所以在做完NativeX之后,接下來的事情就是寫必要程度的庫之后,做一些基礎設施讓托管語言可以被編譯到NativeX上面去。因此現在需要完成的東西有:
1、內存池,用來實現NativeX的new和delete。這個已經做完了。下一篇文章將詳細描述這個內存池的結構。
2、線程和同步對象。這個很快就做完了。NativeX的線程不僅需要有基本的功能,還需要做一個內置的消息循環。當一部分線程選擇使用消息循環作為它的結構的時候,其他線程就可以把一些代碼片段發送給這個線程執行了。并且要做到跟C#一樣,當線程被外部強行中止的時候,線程內部會拋出一個異常,然后讓線程自己去處理。
3、基本的字符串和數學函數庫
4、垃圾收集器。這個垃圾收集器是不屬于NativeX的語法的。這個垃圾收集器將被開發成一個NativeX的函數庫,用于支持更高層次語言的編譯。
當然為了完成這個目標,我給NativeX加上了一些無關痛癢但是卻會帶來方便的語法:
1、#public編譯選項。只要在structure、function或者variable上面標記了#public的話,這個特殊的標志就會被記錄在編譯后的二進制文件的元數據里面。NativeX現在的元數據分為兩種。第一種是運行時元數據。
之前的文章提到NativeX的模板函數和其他模板的東西都是可以直接編譯進二進制文件的,因此模板函數的實例化實際上是在運行是的時候做的。不過現在我也實現了一個編譯選項(不屬于NativeX,需要用C++去控制),
可以在編譯完所有二進制文件之后,將他們合并成一個大的二進制文件并且預先展開所有需要的模板函數。這一步可以用于加快運行速度,還可以為將來運行時編譯成x86或者x64做準備。當#public被記錄到元數據里面之后,編譯器就可以從編譯好的二進制文件里面重新還原出該二進制文件的頭文件。
2、sizeof(type)、offsetof(type::member)、typeof(expression)和typeof(type::member)。這個純粹是為了配合內存池和未來的垃圾收集器而做出來的。當你需要alloc一個東西的時候,你顯然需要知道一個類型的尺寸,而這個是會跟隨著不同的情況而變化的,所以就給出了這些東西,讓編譯器幫助你計算各種跟類型相關的數字。
3、常量定義。這個還沒實現,到時候的語法可能會是constant type name = value;。而且當他被標記上#public之后,就可以在生成頭文件的時候包含該常量了。
為了讓C++可以給NativeX添加外部函數,我做了一個輔助類用來簡化這個過程。舉個例子,我們需要實現一個叫做MemCreate的創建內存池的函數。首先我們需要在NativeX里面聲明它:
1 structure __ForeignHandle
2 {
3 }
4
5 foreign function __ForeignHandle* __MemCreate()
6 alias SystemCoreForeignFunctions.MemCreate;
這里的alias后面的一大串是外部函數的名稱,而__MemCreate則是他對于NativeX的名稱。接下來我們就得在C++實現這個函數了:
1 #include "ScriptingUtilityForeignFunctions.h"
2 #include "..\Languages\LanguageRuntime.h"
3 #include "..\..\Entity\GeneralObjectPoolEntity.h"
4 #include "..\..\Threading.h"
5
6 namespace vl
7 {
8 namespace scripting
9 {
10 namespace utility
11 {
12 using namespace basicil;
13 using namespace entities;
14 using namespace collections;
15
16 class SystemCoreMemoryManagerPlugin : public LanguagePlugin
17 {
18 public:
19 struct PoolPackage
20 {
21 GeneralObjectPool pool;
22 CriticalSection cs;
23
24 PoolPackage(vint poolUnitSize, vint poolUnitCount)
25 :pool(poolUnitSize, poolUnitCount)
26 {
27 }
28 };
29
30 List<Ptr<PoolPackage>> pools;
31 CriticalSection pluginCs;
32
33 class MemCreate : public Object, public IBasicILForeignFunction
34 {
35 protected:
36 SystemCoreMemoryManagerPlugin* plugin;
37 public:
38 MemCreate(SystemCoreMemoryManagerPlugin* _plugin)
39 :plugin(_plugin)
40 {
41 }
42
43 void Invoke(BasicILInterpretor* interpretor, BasicILStack* stack, void* result, void* arguments)
44 {
45 LanguageArgumentReader reader(result, arguments, stack);
46 Ptr<PoolPackage> pool=new PoolPackage(1048576, 256);
47
48 CriticalSection::Scope scope(plugin->pluginCs);
49 plugin->pools.Add(pool);
50 reader.Result<PoolPackage*>()=pool.Obj();
51 }
52 };
53
54 static vint MemAlloc(void* result, void* arguments)
55 {
56 LanguageArgumentReader reader(result, arguments);
57 PoolPackage* pool=reader.NextArgument<PoolPackage*>();
58 vint size=reader.NextArgument<vint>();
59
60 CriticalSection::Scope scope(pool->cs);
61 reader.Result<char*>()=pool->pool.Alloc(size);
62 return reader.BytesToPop();
63 }
64
65 static vint MemFree(void* result, void* arguments)
66 {
67 LanguageArgumentReader reader(result, arguments);
68 PoolPackage* pool=reader.NextArgument<PoolPackage*>();
69 char* pointer=reader.NextArgument<char*>();
70
71 CriticalSection::Scope scope(pool->cs);
72 reader.Result<bool>()=pool->pool.Free(pointer);
73 return reader.BytesToPop();
74 }
75
76 static vint MemIsValidHandle(void* result, void* arguments)
77 {
78 LanguageArgumentReader reader(result, arguments);
79 PoolPackage* pool=reader.NextArgument<PoolPackage*>();
80 char* pointer=reader.NextArgument<char*>();
81
82 CriticalSection::Scope scope(pool->cs);
83 reader.Result<bool>()=pool->pool.IsValid(pointer);
84 return reader.BytesToPop();
85 }
86
87 static vint MemGetHandleSize(void* result, void* arguments)
88 {
89 LanguageArgumentReader reader(result, arguments);
90 PoolPackage* pool=reader.NextArgument<PoolPackage*>();
91 char* pointer=reader.NextArgument<char*>();
92
93 CriticalSection::Scope scope(pool->cs);
94 reader.Result<vint>()=pool->pool.GetSize(pointer);
95 return reader.BytesToPop();
96 }
97
98 static vint MemGetOwnerHandle(void* result, void* arguments)
99 {
100 LanguageArgumentReader reader(result, arguments);
101 PoolPackage* pool=reader.NextArgument<PoolPackage*>();
102 char* pointer=reader.NextArgument<char*>();
103
104 CriticalSection::Scope scope(pool->cs);
105 reader.Result<char*>()=pool->pool.GetHandle(pointer);
106 return reader.BytesToPop();
107 }
108 protected:
109 bool RegisterForeignFunctions(BasicILRuntimeSymbol* symbol)
110 {
111 return
112 symbol->RegisterForeignFunction(L"SystemCoreForeignFunctions", L"MemCreate", new MemCreate(this)) &&
113 symbol->RegisterLightFunction(L"SystemCoreForeignFunctions", L"MemAlloc", MemAlloc) &&
114 symbol->RegisterLightFunction(L"SystemCoreForeignFunctions", L"MemFree", MemFree) &&
115 symbol->RegisterLightFunction(L"SystemCoreForeignFunctions", L"MemIsValidHandle", MemIsValidHandle) &&
116 symbol->RegisterLightFunction(L"SystemCoreForeignFunctions", L"MemGetHandleSize", MemGetHandleSize) &&
117 symbol->RegisterLightFunction(L"SystemCoreForeignFunctions", L"MemGetOwnerHandle", MemGetOwnerHandle);
118 }
119 };
120
121 Ptr<LanguagePlugin> CreateMemoryManagerPlugin()
122 {
123 return new SystemCoreMemoryManagerPlugin();
124 }
125 }
126 }
127 }
外部函數分兩種,一種是需要全局狀態的,而另一種不需要。在不需要的時候,我提供了一個不會跟虛函數打交道的接口來加快(雖然其實可以忽略,只是為了滿足那些有畸形性能欲望的人的心理而已)運行時的性能。
就先說到這里了。NativeX函數庫的測試用例已經開始在做了,可以去
Vczh Library++3.0下載最新代碼之后,在下面的目錄找到:
Library\Scripting\Utility\:這里是外部函數的實現。
UnitTest\Binary\ScriptCoreLibrary\:這里是NativeX將外部函數簡單的封裝起來之后的函數庫,以及他們的測試用例。我為NativeX實現了一個簡單的單元測試框架。
UnitTest\UnitTest\TestScripting_Utility_System_CoreNative.cpp:這個是NativeX單元測試框架的host。
posted on 2011-01-01 05:14
陳梓瀚(vczh) 閱讀(3884)
評論(7) 編輯 收藏 引用 所屬分類:
VL++3.0開發紀事