根据之前的计划,让
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) 阅读(3850)
评论(7) 编辑 收藏 引用 所属分类:
VL++3.0开发纪事