matlab读取pdb文件,GacUI Demo:PDB Viewer(分析pdb文件并获取C++类声明的详细内容)...

GacUI为了实现把界面序列化和反序列化到XML,必然要有类似反射一样的功能。但是C++却没有反射,现在想到的方法就是,把编译后的pdb文件拿出来。因为控件不是模板类,所以数据都可以直接获取。pdb文件包含了所有函数的信息,还有被实例化后的模板类和模板函数的信息。因此只需要使用IDiaDataSource(Visual Studio提供的COM组件)读取pdb的类声明之后,把信息整理并输出到一个xml里面,然后就可以用C#编写linq to xml的程序去分析并生成支持C++反射的一系列周边代码了。这样就自动让C++其中一部分必要的类获得反射的功能,代价就是每一次修改完代码之后,要记得非人肉地更新自动生成的代码。

不过为了更加形象的展示pdb的内容,我使用GacUI的带Virtual Mode的TreeView打开pdb填充。这里面有两个view,第一个是pdb,第二个是整理后的class view。显示pdb的GuiTreeView控件展示了如何通过提供一个数据源,从而实现“展开的时候再从pdb文件里面读取信息”的技术。而class view则是通过提供一个数据源来将一个文件中的xml读取到内存并显示出来,但是避免new那些暂时还不需要显示出来的TreeViewNode对象。代码放在Vczh Library++ 3.0(Candidate\GUI\GUIDemo\GUIDemo.sln)。现在先上图:

3b98bfcba584641d2d7844993c8de3a3.png

62ef59a7c434e44fa8d9b26596b72f7d.png

解析PDB的关键代码在DumpPDB.cpp文件中,大家只需要下载代码并阅读即可。所有的内容都可以从MSDN搜索IDiaDataSource获得,但是运行的话则需要有这个COM组件,一般要求安装Visual Studio。下面解释一下一段C++代码。这是上面那个按钮的回调函数。这个回调函数做了下面几件事情

1、将Button和TagPage都Disable

2、利用线程池异步将PDB的内容保存到XML文件中(一秒钟)

3、第2步完成之后,发一个消息回到GUI线程,自动显示第二个TagPage

4、异步将XML读取到内存。在这里我没有使用延迟读取技术,所以我直接创建了大约几百万个字符串,需要五秒钟

5、第4步完成之后,发一个消息回到GUI线程吗,将创建好的内存中的XML格式显示在TreeView里

这些异步操作来往十分复杂,但是借助C++0x就可以描述得十分清晰。GacUI的实现并没有使用C++0x,但是仍然可以为使用C++0x的那部分用户提供一些更加优化的接口。因此这些复杂的步骤最后就写成了:

buttonDump->Clicked.AttachLambda([=](GuiGraphicsComposition* sender, GuiEventArgs& arguments)

{

INativeController* controller=GetCurrentController();

tabControl->GetPages()[0]->GetContainer()->SetEnabled(false);

buttonDump->SetEnabled(false);

buttonDump->SetText(L"Dumping...");

buttonDump->GetRelatedControlHost()->GetBoundsComposition()->SetAssociatedCursor(controller->GetSystemCursor(INativeCursor::LargeWaiting));

ThreadPoolLite::QueueLambda([=]()

{

dumppdb::DumpPdbToXml(diaSymbol, L"..\\Debug\\GuiDemo.xml");

GetApplication()->InvokeLambdaInMainThread([=]()

{

tabControl->GetPages()[0]->GetContainer()->SetEnabled(true);

tabControl->SetSelectedPage(tabControl->GetPages()[1]);

buttonDump->SetText(L"Loading GuiDemo.xml in the class view...");

ThreadPoolLite::QueueLambda([=]()

{

FileStream fileStream(L"..\\Debug\\GuiDemo.xml", FileStream::ReadOnly);

CacheStream cacheStream(fileStream, 1048576);

BomDecoder decoder;

DecoderStream decoderStream(cacheStream, decoder);

StreamReader reader(decoderStream);

Ptr xml=LoadXmlRawDocument(reader).Cast();

GetApplication()->InvokeLambdaInMainThreadAndWait([=]()

{

buttonDump->SetText(L"GuiDemo.xml dumpped.");

buttonDump->GetRelatedControlHost()->GetBoundsComposition()->SetAssociatedCursor(controller->GetDefaultSystemCursor());

GuiTreeView* treeControl=new GuiTreeView(new win7::Win7TreeViewProvider, CreateProviderFromXml(xml));

treeControl->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0));

treeControl->SetVerticalAlwaysVisible(false);

treeControl->SetHorizontalAlwaysVisible(false);

tabControl->GetPages()[1]->GetContainer()->GetContainerComposition()->AddChild(treeControl->GetBoundsComposition());

});

});

});

});

});

buttonDump->Clicked.AttachLambda的意思是将一个满足C++0x标准的lambda表达式当成一个事件处理程序绑定到一个时间上。ThreadPoolLite::QueueLambda则是将一个lambda表达式放进Windows内核实现的内存池进行异步调用。GetApplication()->InvokeLambdaInMainThread(AndWait)则是在别的线程里将一个lambda表达式放到GUI线程(一般是主线程)中运行。如果调用了Wait的版本,则这个函数会一直等到该lambda表达式在主线程执行完了才会返回。如果大家关心实现的话,可以去Candidate\GUI\GUI\NativeWindow\Windows\WinNativeWindow.cpp文件里查看。

大家可以想象,在古老的不支持lambda表达式的C++版本里面,要实现这个过程,这个函数将被拆散成多少函数。为了传递很多复杂的对象,要写多少个临时的struct,new多少内存碎片才能将异步回调函数的参数做成Windows所希望的DWORD(__stdcall*)(void*)格式。为了把一部分事情放回到GUI线程做(我们都知道GUI库不值得为了线程安全而做很多浪费性能的事情),得实现多少私有的Win32消息,subclass多少东西才能最终做到。这一切在GacUI中都简化了。

接下来将会研究如何利用pdb里面的信息让跟GacUI有关的对象支持反射的具体细节。元旦就先休息了,啊哈哈哈。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值