青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-341  評(píng)論-2670  文章-0  trackbacks-0
    GacUI到了撰寫(xiě)文檔的時(shí)候了。雖然GacUI本身的功能還沒(méi)有全部完成,但是發(fā)布一個(gè)alpha版還是可以的。因此GacUI需要一份文檔。自從.net語(yǔ)言支持XML注釋生成文檔之后,Visual Studio的本地C++也支持使用XML注釋了。只要打開(kāi)了[工程屬性 -> C/C++ -> Output Files -> Generate XML Documentation Files]之后,Visual Studio會(huì)在編譯本地C++工程之后,將所有的XML注釋收集起來(lái),放在和可執(zhí)行文件同一個(gè)目錄下的<ProjectName.xml>里面。然后我就嘗試bing了一下有沒(méi)有從C++的XML文檔生成可讀文檔的工具,結(jié)果發(fā)現(xiàn)只有.net才支持。

    后來(lái)我稍微研究了一下(詳細(xì)內(nèi)容將會(huì)在下一篇博客透露),發(fā)現(xiàn)之所以沒(méi)人寫(xiě)這個(gè)工具,是因?yàn)橹挥?net的可執(zhí)行文件才包含足夠多的元數(shù)據(jù),而且這些元數(shù)據(jù)是必須的,否則無(wú)法生成一個(gè)完整的文檔。舉個(gè)例子,雖然<ProjectName.xml>包含了xml注釋和該注釋所在的符號(hào),但是卻沒(méi)有包含該符號(hào)的結(jié)構(gòu)信息。結(jié)果你試圖生成一個(gè)函數(shù)的文檔的時(shí)候,發(fā)現(xiàn)你獲取不到它的返回類型!不過(guò)這也是情有可原的,因?yàn)楸镜谻++程序根本就沒(méi)有元數(shù)據(jù)。

    由此我聯(lián)想到了之前寫(xiě)程序讀pdb的時(shí)候的一些內(nèi)容,我想到pdb生成的那份xml顯然是可以當(dāng)成元數(shù)據(jù)的。而且我找到了一個(gè)方法,讓你在使用Visual Studio2010的PDB API msdia100.dll的時(shí)候,可以不需要安裝Visual Studio 2010了。下面就來(lái)介紹PDB Dumper的代碼。

    首先是main函數(shù)。main函數(shù)做的工作跟之前的這篇博客說(shuō)的一樣,當(dāng)然還是要?jiǎng)?chuàng)建一個(gè)IDiaSymbol的COM對(duì)象。一般來(lái)說(shuō),COM對(duì)象是需要被注冊(cè)到windows里面(基本上都在注冊(cè)表里)才能使用CoCreateInstance來(lái)創(chuàng)建。但是后來(lái)我發(fā)現(xiàn)msdia100.dll十分良心,還提供了一個(gè)NoRegCoCreate函數(shù),可以在你只有msdia100.dll但卻沒(méi)有注冊(cè)它的COM對(duì)象的情況下創(chuàng)建該對(duì)象:
#include <Windows.h>
#include 
<iostream>
#include 
<string>
#include 
"dia2.h"
#include 
"diacreate.h"

#pragma comment(lib, 
"diaguids.lib")

namespace dumppdb
{
    
extern void DumpPdbToXml(IDiaSymbol* exeSymbol, const wchar_t* xml);
}

IDiaSymbol
* CreateDiaSymbol(const wchar_t* pdbPath)
{
    IDiaDataSource
* pSource=0;
    IDiaSession
* pSession=0;
    IDiaSymbol
* pSymbol=0;
    CoInitialize(NULL);
    
//HRESULT hr = CoCreateInstance(
    
//    CLSID_DiaSource,
    
//    NULL,
    
//    CLSCTX_INPROC_SERVER,
    
//    IID_IDiaDataSource,
    
//    (void**) &pSource
    
//    );
    HRESULT hr = NoRegCoCreate(
        L
"msdia100.dll",
        CLSID_DiaSource,
        IID_IDiaDataSource,
        (
void**&pSource
        );
    
if(SUCCEEDED(hr))
    
if(SUCCEEDED(pSource->loadDataFromPdb(pdbPath)))
    
if(SUCCEEDED(pSource->openSession(&pSession)))
    
if(SUCCEEDED(pSession->get_globalScope(&pSymbol)))
    {
        
return pSymbol;
    }
    
return 0;
}

int wmain(int argc, wchar_t* argv[])
{
    
if(argc==3)
    {
        std::wcout
<<L"importing "<<argv[1]<<std::endl;
        IDiaSymbol
* exeSymbol=CreateDiaSymbol(argv[1]);
        
if(exeSymbol)
        {
            std::wcout
<<L"exporting "<<argv[2]<<std::endl;
            dumppdb::DumpPdbToXml(exeSymbol, argv[
2]);
            std::wcout
<<L"exported "<<argv[2]<<std::endl;
        }
        
else
        {
            std::wcout
<<L"Failed to read pdb("<<argv[1]<<L")"<<std::endl;
        }
    }
    
else
    {
        std::wcout
<<L"Pdb2Xml.exe <pdb-path> <xml-path>"<<std::endl;
    }
    
return 0;
}

    這里的dia2.h、diacreate.h、diaguids.lib和msdia100.dll都可以在C:\Program Files (x86)\Microsoft Visual Studio 10.0\DIA SDK下找到。我們需要做的就是將這些文件都復(fù)制到我們的工程目錄下面。至于如何讀取IDiaSymbol的內(nèi)容,各位就自己查MSDN了。下面貼出我使用IDiaSymbol將PDB的關(guān)鍵內(nèi)容輸出成xml的函數(shù),也就是上面的代碼提到的DumpPdbToXml函數(shù)了:

#include "Dia2.h"
#include 
"..\..\..\..\..\Library\Stream\Accessor.h"
#include 
"..\..\..\..\..\Library\Stream\CharFormat.h"
#include 
"..\..\..\..\..\Library\Stream\FileStream.h"
#include 
"..\..\..\..\..\Library\Stream\CacheStream.h"
#include 
"..\..\..\..\..\Library\Collections\Dictionary.h"

using namespace vl;
using namespace vl::collections;
using namespace vl::stream;

namespace dumppdb
{

    
//--------------------------------------------------------------------

    
void PrintString(TextWriter& file, const wchar_t* text, int len=-1)
    {
        
if(len==-1) len=(int)wcslen(text);
        file.WriteString(text, len);
    }

    
void PrintSpaces(TextWriter& file, int level)
    {
        
for(int i=0;i<level;i++) PrintString(file, L"  ");
    }

    
void PrintEscapedName(TextWriter& file, const wchar_t* name)
    {
        
const wchar_t* head=name;
        
const wchar_t* reading=head;
        
while(*reading)
        {
            
switch(*reading)
            {
            
case L'<':
                PrintString(file, head, reading
-head);
                PrintString(file, L
"&lt;");
                head
=reading+1;
                reading
=head;
                
break;
            
case L'>':
                PrintString(file, head, reading
-head);
                PrintString(file, L
"&gt;");
                head
=reading+1;
                reading
=head;
                
break;
            
case L'&':
                PrintString(file, head, reading
-head);
                PrintString(file, L
"&amp;");
                head
=reading+1;
                reading
=head;
                
break;
            
case L'\"':
                PrintString(file, head, reading
-head);
                PrintString(file, L
"&quot;");
                head
=reading+1;
                reading
=head;
                
break;
            
default:
                reading
++;
            }
        }
        PrintString(file, head, reading
-head);
    }

    
void PrintXMLOpen(
        TextWriter
& file, int level, const wchar_t* tagName, const wchar_t* symbolName
        ,
const wchar_t* a1=0const wchar_t* v1=0
        ,
const wchar_t* a2=0const wchar_t* v2=0
        ,
const wchar_t* a3=0const wchar_t* v3=0
        )
    {
        PrintSpaces(file, level);
        PrintString(file, L
"<");
        PrintString(file, tagName);
        
if(symbolName)
        {
            PrintString(file, L
" name=\"");
            PrintEscapedName(file, symbolName);
            PrintString(file, L
"\"");
        }
        
if(a1)
        {
            PrintString(file, L
" ");
            PrintString(file, a1);
            PrintString(file, L
"=\"");
            PrintEscapedName(file, v1);
            PrintString(file, L
"\"");
        }
        
if(a2)
        {
            PrintString(file, L
" ");
            PrintString(file, a2);
            PrintString(file, L
"=\"");
            PrintEscapedName(file, v2);
            PrintString(file, L
"\"");
        }
        
if(a3)
        {
            PrintString(file, L
" ");
            PrintString(file, a3);
            PrintString(file, L
"=\"");
            PrintEscapedName(file, v3);
            PrintString(file, L
"\"");
        }
        PrintString(file, L
" >\r\n");
    }

    
void PrintXMLClose(TextWriter& file, int level, const wchar_t* tagName)
    {
        PrintSpaces(file, level);
        PrintString(file, L
"</");
        PrintString(file, tagName);
        PrintString(file, L
">\r\n");
    }

    
//--------------------------------------------------------------------

    Dictionary
<WString, IDiaSymbol*> udtSymbols;
    Dictionary
<WString, IDiaSymbol*> funcSymbols;

    
void AddOrRelease(Dictionary<WString, IDiaSymbol*>& symbols, IDiaSymbol* symbol)
    {
        
// get name
        BSTR nameBSTR=0;
        
if(SUCCEEDED(symbol->get_name(&nameBSTR)) && nameBSTR)
        {
            WString name
=nameBSTR;
            
if(!symbols.Keys().Contains(name))
            {
                
// record class symbol
                symbols.Add(name, symbol);
                symbol
=0;
            }
        }
        
if(symbol) symbol->Release();
    }

    
void AddUdtOrRelease(IDiaSymbol* udtType)
    {
        AddOrRelease(udtSymbols, udtType);
    }

    
void AddFuncOrRelease(IDiaSymbol* funcSymbol)
    {
        AddOrRelease(funcSymbols, funcSymbol);
    }

    
void FindClasses(IDiaSymbol* exeSymbol)
    {
        {
            
// enumerate classes
            IDiaEnumSymbols* udtEnum=0;
            
if(SUCCEEDED(exeSymbol->findChildren(SymTagUDT, NULL, nsNone, &udtEnum)))
            {
                DWORD udtCelt
=0;
                IDiaSymbol
* udtSymbol=0;
                
while(SUCCEEDED(udtEnum->Next(1&udtSymbol, &udtCelt)) && udtSymbol && udtCelt)
                {
                    AddUdtOrRelease(udtSymbol);
                }
            }
        }
        {
            
// enumerate enums
            IDiaEnumSymbols* enumEnum=0;
            
if(SUCCEEDED(exeSymbol->findChildren(SymTagEnum, NULL, nsNone, &enumEnum)))
            {
                DWORD enumCelt
=0;
                IDiaSymbol
* enumSymbol=0;
                
while(SUCCEEDED(enumEnum->Next(1&enumSymbol, &enumCelt)) && enumSymbol && enumCelt)
                {
                    AddUdtOrRelease(enumSymbol);
                }
            }
        }
        {
            
// enumerate compilands
            IDiaEnumSymbols* compilandEnum=0;
            
if(SUCCEEDED(exeSymbol->findChildren(SymTagCompiland, NULL, nsNone, &compilandEnum)))
            {
                DWORD compilandCelt
=0;
                IDiaSymbol
* compilandSymbol=0;
                
while(SUCCEEDED(compilandEnum->Next(1&compilandSymbol, &compilandCelt)) && compilandSymbol && compilandCelt)
                {
                    
// enumerate functions
                    IDiaEnumSymbols* functionEnum=0;
                    
if(SUCCEEDED(compilandSymbol->findChildren(SymTagFunction, NULL, nsNone, &functionEnum)))
                    {
                        DWORD functionCelt
=0;
                        IDiaSymbol
* functionSymbol=0;
                        
while(SUCCEEDED(functionEnum->Next(1&functionSymbol, &functionCelt)) && functionSymbol && functionCelt)
                        {
                            IDiaSymbol
* udtType=0;
                            
if(SUCCEEDED(functionSymbol->get_classParent(&udtType)) && udtType)
                            {
                                AddUdtOrRelease(udtType);
                                functionSymbol
->Release();
                            }
                            
else
                            {
                                AddFuncOrRelease(functionSymbol);
                            }
                        }
                        functionEnum
->Release();
                    }
                    compilandSymbol
->Release();
                }
                compilandEnum
->Release();
            }
        }
    }

    
//--------------------------------------------------------------------

    
const wchar_t* GetAccessName(enum CV_access_e access)
    {
        
switch(access)
        {
        
case CV_private: return L"private";
        
case CV_protected: return L"protected";
        
case CV_public: return L"public";
        
defaultreturn L"";
        }
    }

    
const wchar_t* GetCallingConversionName(enum CV_call_e callconv)
    {
        
switch(callconv)
        {
        
case CV_CALL_NEAR_C: return L"cdecl";
        
case CV_CALL_NEAR_FAST: return L"fastcall";
        
case CV_CALL_NEAR_STD: return L"stdcall";
        
case CV_CALL_NEAR_SYS: return L"syscall";
        
case CV_CALL_THISCALL: return L"thiscall";
        
case CV_CALL_CLRCALL: return L"clrcall";
        
defaultreturn L"";
        }
    }

    
const wchar_t* GetBasicTypeName(enum BasicType type, int length)
    {
        
switch(type)
        {
        
case btVoid:        return L"void";
        
case btChar:        return L"char";
        
case btWChar:        return L"wchar_t";
        
case btInt:
        
case btLong:        return length==1?L"signed __int8":length==2?L"signed __int16":length==4?L"signed __int32":length==8?L"signed __int64":L"[UnknownSInt]";
        
case btUInt:
        
case btULong:        return length==1?L"unsigned __int8":length==2?L"unsigned __int16":length==4?L"unsigned __int32":length==8?L"unsigned __int64":L"[UnknownUInt]";
        
case btFloat:        return length==4?L"float":length==8?L"double":L"[UnknownFloat]";
        
case btBool:        return L"bool";

        
case btBCD:            return L"[BCD]";
        
case btCurrency:    return L"[Currency]";
        
case btDate:        return L"[Date]";
        
case btVariant:        return L"[Variant]";
        
case btComplex:        return L"[Complex]";
        
case btBit:            return L"[Bit]";
        
case btBSTR:        return L"[BSTR]";
        
case btHresult:        return L"[HRESULT]";
        
default:            return L"[NoType]";
        }
    }

    
//--------------------------------------------------------------------

    
extern void DumpType(TextWriter& file, IDiaSymbol* typeSymbol, int level);

    
void DumpTypeHelper(TextWriter& file, IDiaSymbol* typeSymbol, int level, const wchar_t* tagName, const wchar_t* symbolName, bool close=true)
    {
        BOOL constType
=FALSE, volatileType=FALSE;
        typeSymbol
->get_constType(&constType);
        typeSymbol
->get_volatileType(&volatileType);
        PrintXMLOpen(file, level, tagName, symbolName, L
"const", (constType?L"true":L"false"), L"volatile", (volatileType?L"true":L"false"));
        
if(close)
        {
            PrintXMLClose(file, level, tagName);
        }
    }

    
void DumpFunctionType(TextWriter& file, IDiaSymbol* typeSymbol, int level)
    {
        DumpTypeHelper(file, typeSymbol, level, L
"function", NULL, false);
        {
            CV_call_e callconv;
            typeSymbol
->get_callingConvention((DWORD*)&callconv);
            PrintXMLOpen(file, level
+1, L"callconv", NULL, L"value", GetCallingConversionName(callconv));
            PrintXMLClose(file, level
+1, L"callconv");
            PrintXMLOpen(file, level
+1, L"arguments", NULL);
            {
                IDiaEnumSymbols
* argumentEnum=0;
                
if(SUCCEEDED(typeSymbol->findChildren(SymTagFunctionArgType, NULL, nsNone, &argumentEnum)) && argumentEnum)
                {
                    DWORD argumentCelt
=0;
                    IDiaSymbol
* argumentSymbol=0;
                    
while(SUCCEEDED(argumentEnum->Next(1&argumentSymbol, &argumentCelt)) && argumentSymbol && argumentCelt)
                    {
                        IDiaSymbol
* argumentType=0;
                        
if(SUCCEEDED(argumentSymbol->get_type(&argumentType)))
                        {
                            PrintXMLOpen(file, level
+2, L"argument", NULL);
                            DumpType(file, argumentType, level
+3);
                            PrintXMLClose(file, level
+2, L"argument");
                            argumentType
->Release();
                        }
                        argumentSymbol
->Release();
                    }
                    argumentEnum
->Release();
                }
            }
            PrintXMLClose(file, level
+1, L"arguments");
        }
        IDiaSymbol
* returnTypeSymbol=0;
        
if(SUCCEEDED(typeSymbol->get_type(&returnTypeSymbol)) && returnTypeSymbol)
        {
            PrintXMLOpen(file, level
+1, L"return", NULL);
            DumpType(file, returnTypeSymbol, level
+2);
            PrintXMLClose(file, level
+1, L"return");
            returnTypeSymbol
->Release();
        }
        PrintXMLClose(file, level, L
"function");
    }

    
void DumpPointerType(TextWriter& file, IDiaSymbol* typeSymbol, int level)
    {
        IDiaSymbol
* elementTypeSymbol=0;
        
if(SUCCEEDED(typeSymbol->get_type(&elementTypeSymbol)) && elementTypeSymbol)
        {
            BOOL lref
=FALSE;
            BOOL rref
=FALSE;
            typeSymbol
->get_reference(&lref);
            typeSymbol
->get_RValueReference(&rref);
            
if(lref)
            {
                DumpTypeHelper(file, typeSymbol, level, L
"reference", NULL, false);
                DumpType(file, elementTypeSymbol, level
+1);
                PrintXMLClose(file, level, L
"reference");
            }
            
else if(rref)
            {
                DumpTypeHelper(file, typeSymbol, level, L
"rightValueReference", NULL, false);
                DumpType(file, elementTypeSymbol, level
+1);
                PrintXMLClose(file, level, L
"rightValueReference");
            }
            
else
            {
                DumpTypeHelper(file, typeSymbol, level, L
"pointer", NULL, false);
                DumpType(file, elementTypeSymbol, level
+1);
                PrintXMLClose(file, level, L
"pointer");
            }
            elementTypeSymbol
->Release();
        }
    }

    
void DumpArrayType(TextWriter& file, IDiaSymbol* typeSymbol, int level)
    {
        IDiaSymbol
* indexTypeSymbol=0;
        IDiaSymbol
* elementTypeSymbol=0;
        
if(SUCCEEDED(typeSymbol->get_type(&elementTypeSymbol)) && elementTypeSymbol)
        {
            ULONGLONG arraySize
=0, elementSize=0;
            typeSymbol
->get_length(&arraySize);
            elementTypeSymbol
->get_length(&elementSize);
            
int elementCount=arraySize?(int)(arraySize/elementSize):0;
            wchar_t elementCountBuffer[
20];
            _itow_s(elementCount, elementCountBuffer, 
10);
            
            DumpTypeHelper(file, typeSymbol, level, L
"array", NULL, false);
            PrintXMLOpen(file, level
+1, L"count", NULL, L"value", elementCountBuffer);
            PrintXMLClose(file, level
+1, L"count");
            
if(SUCCEEDED(typeSymbol->get_arrayIndexType(&indexTypeSymbol)) && indexTypeSymbol)
            {
                PrintXMLOpen(file, level
+1, L"index", NULL);
                DumpType(file, indexTypeSymbol, level
+2);
                PrintXMLClose(file, level
+1, L"index");
                indexTypeSymbol
->Release();
            }
            PrintXMLOpen(file, level
+1, L"element", NULL);
            DumpType(file, elementTypeSymbol, level
+2);
            PrintXMLClose(file, level
+1, L"element");
            PrintXMLClose(file, level, L
"array");
            elementTypeSymbol
->Release();
        }
    }

    
void DumpBaseType(TextWriter& file, IDiaSymbol* typeSymbol, int level)
    {
        
enum BasicType basicType=btNoType;
        ULONGLONG length
=0;
        
if(SUCCEEDED(typeSymbol->get_baseType((DWORD*)&basicType)) && SUCCEEDED(typeSymbol->get_length(&length)))
        {
            DumpTypeHelper(file, typeSymbol, level, L
"primitive", GetBasicTypeName(basicType, (int)length));
        }
    }

    
void DumpEnumType(TextWriter& file, IDiaSymbol* typeSymbol, int level)
    {
        BSTR nameBSTR
=0;
        
if(SUCCEEDED(typeSymbol->get_name(&nameBSTR)) && nameBSTR)
        {
            DumpTypeHelper(file, typeSymbol, level, L
"enumType", nameBSTR);
        }
    }

    
void DumpUserType(TextWriter& file, IDiaSymbol* typeSymbol, int level)
    {
        BSTR nameBSTR
=0;
        
if(SUCCEEDED(typeSymbol->get_name(&nameBSTR)) && nameBSTR)
        {
            DumpTypeHelper(file, typeSymbol, level, L
"classType", nameBSTR);
        }
    }

    
void DumpType(TextWriter& file, IDiaSymbol* typeSymbol, int level)
    {
        
enum SymTagEnum symTag=SymTagNull;
        typeSymbol
->get_symTag((DWORD*)&symTag);
        
switch(symTag)
        {
        
case SymTagFunctionType:
            
return DumpFunctionType(file, typeSymbol, level);
        
case SymTagPointerType:
            
return DumpPointerType(file, typeSymbol, level);
        
case SymTagArrayType:
            
return DumpArrayType(file, typeSymbol, level);
        
case SymTagBaseType:
            
return DumpBaseType(file, typeSymbol, level);
        
case SymTagEnum:
            
return DumpUserType(file, typeSymbol, level);
        
case SymTagUDT:
            
return DumpUserType(file, typeSymbol, level);
        }
    }

    
void DumpSymbolType(TextWriter& file, IDiaSymbol* symbolWithType, int symbolLevel)
    {
        IDiaSymbol
* typeSymbol=0;
        
if(SUCCEEDED(symbolWithType->get_type(&typeSymbol)) && typeSymbol)
        {
            PrintXMLOpen(file, symbolLevel
+1, L"type", NULL);
            DumpType(file, typeSymbol, symbolLevel
+2);
            PrintXMLClose(file, symbolLevel
+1, L"type");
            typeSymbol
->Release();
        }
    }

    
//--------------------------------------------------------------------

    
void DumpBaseClasses(TextWriter& file, IDiaSymbol* udtSymbol)
    {
        PrintXMLOpen(file, 
2, L"baseClasses", NULL, false);
        IDiaEnumSymbols
* baseClassEnum=0;
        
if(SUCCEEDED(udtSymbol->findChildren(SymTagBaseClass, NULL, nsNone, &baseClassEnum)) && baseClassEnum)
        {
            DWORD baseClassCelt
=0;
            IDiaSymbol
* baseClassSymbol=0;
            
while(SUCCEEDED(baseClassEnum->Next(1&baseClassSymbol, &baseClassCelt)) && baseClassSymbol && baseClassCelt)
            {
                CV_access_e access
=CV_public;
                baseClassSymbol
->get_access((DWORD*)&access);

                BSTR nameBSTR
=0;
                
if(SUCCEEDED(baseClassSymbol->get_name(&nameBSTR)) && nameBSTR)
                {
                    PrintXMLOpen(file, 
3, L"baseClass", nameBSTR, L"access", GetAccessName(access));
                    PrintXMLClose(file, 
3, L"baseClass");
                }
                baseClassSymbol
->Release();
            }
            baseClassEnum
->Release();
        }
        PrintXMLClose(file, 
2, L"baseClasses");
    }

    
void DumpNestedClasses(TextWriter& file, IDiaSymbol* udtSymbol)
    {
        PrintXMLOpen(file, 
2, L"nestedClasses", NULL, false);
        IDiaEnumSymbols
* nestedClassEnum=0;
        
if(SUCCEEDED(udtSymbol->findChildren(SymTagUDT, NULL, nsNone, &nestedClassEnum)) && nestedClassEnum)
        {
            DWORD nestedClassCelt
=0;
            IDiaSymbol
* nestedClassSymbol=0;
            
while(SUCCEEDED(nestedClassEnum->Next(1&nestedClassSymbol, &nestedClassCelt)) && nestedClassSymbol && nestedClassCelt)
            {
                BSTR nameBSTR
=0;
                
if(SUCCEEDED(nestedClassSymbol->get_name(&nameBSTR)) && nameBSTR)
                {
                    PrintXMLOpen(file, 
3, L"nestedClass", nameBSTR);
                    PrintXMLClose(file, 
3, L"nestedClass");
                }
                nestedClassSymbol
->Release();
            }
            nestedClassEnum
->Release();
        }
        PrintXMLClose(file, 
2, L"nestedClasses");
    }

    
void DumpTypedefs(TextWriter& file, IDiaSymbol* udtSymbol)
    {
        PrintXMLOpen(file, 
2, L"typedefs", NULL, false);
        IDiaEnumSymbols
* typedefEnum=0;
        
if(SUCCEEDED(udtSymbol->findChildren(SymTagTypedef, NULL, nsNone, &typedefEnum)) && typedefEnum)
        {
            DWORD typedefCelt
=0;
            IDiaSymbol
* typedefSymbol=0;
            
while(SUCCEEDED(typedefEnum->Next(1&typedefSymbol, &typedefCelt)) && typedefSymbol && typedefCelt)
            {
                BSTR nameBSTR
=0;
                
if(SUCCEEDED(typedefSymbol->get_name(&nameBSTR)) && nameBSTR)
                {
                    PrintXMLOpen(file, 
3, L"typedef", nameBSTR);
                    DumpSymbolType(file, typedefSymbol, 
3);
                    PrintXMLClose(file, 
3, L"typedef");
                }
                typedefSymbol
->Release();
            }
            typedefEnum
->Release();
        }
        PrintXMLClose(file, 
2, L"typedefs");
    }

    
void DumpFields(TextWriter& file, IDiaSymbol* udtSymbol)
    {
        PrintXMLOpen(file, 
2, L"fields", NULL);
        IDiaEnumSymbols
* fieldEnum=0;
        
if(SUCCEEDED(udtSymbol->findChildren(SymTagData, NULL, nsNone, &fieldEnum)) && fieldEnum)
        {
            DWORD fieldCelt
=0;
            IDiaSymbol
* fieldSymbol=0;
            
while(SUCCEEDED(fieldEnum->Next(1&fieldSymbol, &fieldCelt)) && fieldSymbol && fieldCelt)
            {
                
enum DataKind dataKind;
                
if(SUCCEEDED(fieldSymbol->get_dataKind((DWORD*)&dataKind)) && (dataKind==DataIsMember || dataKind==DataIsStaticMember || dataKind==DataIsConstant))
                {
                    
enum CV_access_e access;
                    fieldSymbol
->get_access((DWORD*)&access);
                    BSTR nameBSTR
=0;
                    
if(SUCCEEDED(fieldSymbol->get_name(&nameBSTR)) && nameBSTR)
                    {
                        
if(dataKind==DataIsMember)
                        {
                            PrintXMLOpen(file, 
3, L"field", nameBSTR, L"access", GetAccessName(access));
                            DumpSymbolType(file, fieldSymbol, 
3);
                            PrintXMLClose(file, 
3, L"field");
                        }
                        
else if(dataKind==DataIsStaticMember)
                        {
                            PrintXMLOpen(file, 
3, L"staticField", nameBSTR, L"access", GetAccessName(access));
                            DumpSymbolType(file, fieldSymbol, 
3);
                            PrintXMLClose(file, 
3, L"staticField");
                        }
                        
else if(dataKind==DataIsConstant)
                        {
                            PrintXMLOpen(file, 
3, L"const", nameBSTR, L"access", GetAccessName(access));
                            DumpSymbolType(file, fieldSymbol, 
3);
                            {
                                VARIANT value;
                                value.vt 
= VT_EMPTY;
                                
if (fieldSymbol->get_value(&value) == S_OK)
                                {
                                    signed __int64 ivalue
=0;
                                    
switch(value.vt)
                                    {
                                    
case VT_I1:
                                        ivalue
=value.cVal;
                                        
goto PROCESS_INTEGER;
                                    
case VT_I2:
                                        ivalue
=value.iVal;
                                        
goto PROCESS_INTEGER;
                                    
case VT_I4:
                                        ivalue
=value.lVal;
                                        
goto PROCESS_INTEGER;
                                    
case VT_UI1:
                                        ivalue
=value.bVal;
                                        
goto PROCESS_INTEGER;
                                    
case VT_UI2:
                                        ivalue
=value.uiVal;
                                        
goto PROCESS_INTEGER;
                                    
case VT_UI4:
                                        ivalue
=value.ulVal;
                                        
goto PROCESS_INTEGER;
                                    PROCESS_INTEGER:
                                        wchar_t valueBuffer[
100];
                                        _i64tow_s(ivalue, valueBuffer, 
10010);
                                        PrintXMLOpen(file, 
4, L"intValue", NULL, L"value", valueBuffer);
                                        PrintXMLClose(file, 
4, L"intValue");
                                        
break;
                                    }
                                }
                            }
                            PrintXMLClose(file, 
3, L"const");
                        }
                    }
                }
                fieldSymbol
->Release();
            }
            fieldEnum
->Release();
        }
        PrintXMLClose(file, 
2, L"fields");
    }

    
void DumpMethodArguments(TextWriter& file, IDiaSymbol* methodSymbol)
    {
        PrintXMLOpen(file, 
4, L"arguments", NULL);
        IDiaEnumSymbols
* argumentEnum=0;
        
if(SUCCEEDED(methodSymbol->findChildren(SymTagData, NULL, nsNone, &argumentEnum)) && argumentEnum)
        {
            DWORD argumentCelt
=0;
            IDiaSymbol
* argumentSymbol=0;
            
while(SUCCEEDED(argumentEnum->Next(1&argumentSymbol, &argumentCelt)) && argumentSymbol && argumentCelt)
            {
                
enum DataKind dataKind;
                
if(SUCCEEDED(argumentSymbol->get_dataKind((DWORD*)&dataKind)) && dataKind==DataIsParam)
                {
                    BSTR nameBSTR
=0;
                    
if(SUCCEEDED(argumentSymbol->get_name(&nameBSTR)) && nameBSTR)
                    {
                        PrintXMLOpen(file, 
5, L"argument", nameBSTR);
                        DumpSymbolType(file, argumentSymbol, 
5);
                        PrintXMLClose(file, 
5, L"argument");
                    }
                }
                argumentSymbol
->Release();
            }
            argumentEnum
->Release();
        }
        PrintXMLClose(file, 
4, L"arguments");
    }

    
void DumpMethod(TextWriter& file, IDiaSymbol* methodSymbol)
    {
        
enum CV_access_e access;
        methodSymbol
->get_access((DWORD*)&access);
        BOOL staticMethod
=FALSE;
        methodSymbol
->get_isStatic(&staticMethod);
        BSTR nameBSTR
=0;

        
const wchar_t* virtualValue=L"normal";
        BOOL virtualBool
=FALSE;
        
if(SUCCEEDED(methodSymbol->get_pure(&virtualBool)) && virtualBool)
        {
            virtualValue
=L"pure";
        }
        
else if(SUCCEEDED(methodSymbol->get_virtual(&virtualBool)) && virtualBool)
        {
            virtualValue
=L"virtual";
        }
        
if(SUCCEEDED(methodSymbol->get_name(&nameBSTR)) && nameBSTR)
        {
            
if(staticMethod)
            {
                PrintXMLOpen(file, 
3, L"staticMethod", nameBSTR, L"access", GetAccessName(access), L"virtual", virtualValue);
                DumpMethodArguments(file, methodSymbol);
                DumpSymbolType(file, methodSymbol, 
3);
                PrintXMLClose(file, 
3, L"staticMethod");
            }
            
else
            {
                PrintXMLOpen(file, 
3, L"method", nameBSTR, L"access", GetAccessName(access), L"virtual", virtualValue);
                DumpMethodArguments(file, methodSymbol);
                DumpSymbolType(file, methodSymbol, 
3);
                PrintXMLClose(file, 
3, L"method");
            }
        }
    }

    
void DumpMethods(TextWriter& file, IDiaSymbol* udtSymbol)
    {
        PrintXMLOpen(file, 
2, L"methods", NULL);
        IDiaEnumSymbols
* methodEnum=0;
        
if(SUCCEEDED(udtSymbol->findChildren(SymTagFunction, NULL, nsNone, &methodEnum)) && methodEnum)
        {
            DWORD methodCelt
=0;
            IDiaSymbol
* methodSymbol=0;
            
while(SUCCEEDED(methodEnum->Next(1&methodSymbol, &methodCelt)) && methodSymbol && methodCelt)
            {
                DumpMethod(file, methodSymbol);
                methodSymbol
->Release();
            }
            methodEnum
->Release();
        }
        PrintXMLClose(file, 
2, L"methods");
    }

    
void Dump(TextWriter& file, IDiaSymbol* exeSymbol)
    {
        FindClasses(exeSymbol);

        
for(int i=0;i<udtSymbols.Count();i++)
        {
            WString className
=udtSymbols.Keys()[i];
            IDiaSymbol
* classSymbol=udtSymbols.Values()[i];
            
enum SymTagEnum symTag=SymTagNull;
            classSymbol
->get_symTag((DWORD*)&symTag);
            
if(symTag==SymTagUDT)
            {
                PrintXMLOpen(file, 
1, L"class", className.Buffer());
                DumpBaseClasses(file, classSymbol);
                DumpNestedClasses(file, classSymbol);
                DumpTypedefs(file, classSymbol);
                DumpFields(file, classSymbol);
                DumpMethods(file, classSymbol);
                PrintXMLClose(file, 
1, L"class");
            }
            
else if(symTag==SymTagEnum)
            {
                PrintXMLOpen(file, 
1, L"enum", className.Buffer());
                DumpFields(file, classSymbol);
                PrintXMLClose(file, 
1, L"enum");
            }
        }
        
for(int i=0;i<udtSymbols.Count();i++)
        {
            udtSymbols.Values()[i]
->Release();
        }
        udtSymbols.Clear();

        PrintXMLOpen(file, 
1, L"functions", NULL);
        
for(int i=0;i<funcSymbols.Count();i++)
        {
            WString funcName
=funcSymbols.Keys()[i];
            IDiaSymbol
* funcSymbol=funcSymbols.Values()[i];
            DumpMethod(file, funcSymbol);
        }
        PrintXMLClose(file, 
1, L"functions");
        
for(int i=0;i<funcSymbols.Count();i++)
        {
            funcSymbols.Values()[i]
->Release();
        }
        funcSymbols.Clear();
    }

    
void DumpPdbToXml(IDiaSymbol* exeSymbol, const wchar_t* xml)
    {
        FileStream fileStream(xml, FileStream::WriteOnly);
        CacheStream cacheStream(fileStream, 
1048576);
        BomEncoder encoder(BomEncoder::Utf16);
        EncoderStream encoderStream(cacheStream, encoder);
        StreamWriter file(encoderStream);
        PrintString(file, L
"<?xml version=\"1.0\" encoding=\"utf-16\" ?>\r\n");
        PrintXMLOpen(file, 
0, L"pdb", NULL);
        Dump(file, exeSymbol);
        PrintXMLClose(file, 
0, L"pdb");
    }
}

    下一篇文章將講到我如何使用上面的程序產(chǎn)生的xml和Visual Studio的本地C++編譯器生成的XML文檔,來(lái)合并成一個(gè)完整的XML描述的文檔。
posted on 2012-03-09 14:43 陳梓瀚(vczh) 閱讀(7077) 評(píng)論(0)  編輯 收藏 引用 所屬分類: C++GacUI
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            免费成人av在线| 亚洲一区二区三区精品动漫| 麻豆精品在线观看| 一本色道久久88精品综合| 久久夜色精品国产欧美乱| 国产精品日韩一区二区| 亚洲私人黄色宅男| 亚洲久久成人| 欧美freesex8一10精品| 亚洲电影免费观看高清完整版在线 | 久久亚洲高清| 亚洲一区二区三区激情| 久久久久.com| 国产日韩欧美电影在线观看| 中文在线资源观看视频网站免费不卡| 久久精品视频导航| 亚洲在线观看视频| 国产精品亚洲视频| 亚洲综合色婷婷| 夜夜嗨av色一区二区不卡| 欧美激情精品久久久久久大尺度| 久久国产精品免费一区| 99re国产精品| 亚洲成色777777在线观看影院| 亚洲自拍偷拍福利| 欧美午夜电影在线| 亚洲天堂av图片| 亚洲日本免费电影| 欧美国产欧美亚洲国产日韩mv天天看完整 | 欧美在线不卡| 国外成人性视频| 米奇777超碰欧美日韩亚洲| 午夜精品亚洲一区二区三区嫩草| 国产精品欧美一区二区三区奶水 | 亚洲精品久久久久久久久| 欧美不卡在线视频| 欧美激情精品久久久久久蜜臀 | 亚洲综合色网站| 欧美人与性禽动交情品| 亚洲一区免费在线观看| 午夜精品久久久久久久白皮肤 | 亚洲人精品午夜| 亚洲人线精品午夜| 国产精品欧美日韩一区二区| 午夜伦欧美伦电影理论片| 欧美在线地址| 亚洲精品影视在线观看| 亚洲一区日本| 亚洲区在线播放| 亚洲一区国产视频| 亚洲人线精品午夜| 午夜视频在线观看一区二区| 亚洲激情第一区| 亚洲综合成人婷婷小说| 亚洲人成网站色ww在线 | 欧美性视频网站| 久久久久久综合| 欧美日韩激情小视频| 久久精品二区| 欧美日韩一区不卡| 欧美a级大片| 亚洲欧美日本在线| 亚洲激情啪啪| 欧美有码在线视频| 亚洲在线一区二区| 农村妇女精品| 久久亚洲精品欧美| 国产精品一区二区三区四区五区| 亚洲国产精品电影| 久久免费视频在线观看| 欧美好吊妞视频| 久久久在线视频| 欧美视频中文在线看| 牛人盗摄一区二区三区视频| 国产精品高清免费在线观看| 亚洲国产精品第一区二区三区| 国产精品美腿一区在线看| 亚洲激情校园春色| 亚洲国产精品久久久久秋霞蜜臀| 午夜精品福利在线观看| 亚洲欧美国产精品桃花| 欧美日本网站| 亚洲精品系列| 99精品久久| 欧美国产日韩二区| 欧美激情视频给我| 亚洲黄色一区| 免费欧美网站| 亚洲第一精品电影| 亚洲人成亚洲人成在线观看| 久久精品欧洲| 麻豆精品精华液| 一区在线免费| 老司机67194精品线观看| 久久综合伊人77777| 狠狠色综合网| 久久国产精品久久久| 久久久久久亚洲精品杨幂换脸| 国产人久久人人人人爽| 亚洲女人av| 久久久久国产精品午夜一区| 国产在线日韩| 久久视频在线视频| 亚洲高清123| aⅴ色国产欧美| 欧美日韩高清一区| 亚洲视频免费在线| 欧美亚洲免费电影| 国产精品人成在线观看免费 | 欧美一区二区三区在线| 欧美精品久久一区二区| 日韩视频一区二区三区| 亚洲一区精品视频| 国产亚洲欧美一区| 麻豆精品网站| 亚洲精品一区二区三区在线观看 | 欧美va亚洲va日韩∨a综合色| 狠狠色噜噜狠狠色综合久| 老司机精品导航| 亚洲日本视频| 午夜精品三级视频福利| 国语精品一区| 欧美精品亚洲二区| 91久久久亚洲精品| 亚洲私人影院| 国产一区二区三区久久| 另类激情亚洲| 亚洲欧美日韩直播| 激情成人av| 欧美日本成人| 性欧美18~19sex高清播放| 欧美成人午夜剧场免费观看| 亚洲性xxxx| 亚洲第一天堂av| 亚洲午夜国产成人av电影男同| 久久久精品tv| aⅴ色国产欧美| 一区二区三区我不卡| 欧美日韩国产区| 久久夜色精品国产噜噜av| 亚洲美女色禁图| 欧美a级一区二区| 亚洲欧美日韩电影| 最新成人av在线| 国产日韩欧美中文| 欧美日韩一区二区三区四区在线观看| 亚洲欧美美女| 亚洲精品免费在线播放| 久久久精品999| 亚洲中午字幕| 99热在线精品观看| 久久亚洲综合色| 一区二区三区色| 精品电影在线观看| 国产精品乱码妇女bbbb| 免费亚洲一区| 久久婷婷激情| 欧美综合国产| 亚洲免费影院| 99热免费精品在线观看| 玉米视频成人免费看| 国产精品国产三级国产专播精品人| 久久久久久网| 午夜视频在线观看一区二区| 一本色道久久综合精品竹菊 | 亚洲欧美日本国产有色| 日韩视频免费观看| 亚洲大胆av| 正在播放欧美一区| 免费观看成人| 久久久亚洲高清| 久久国产精品毛片| 欧美一区二区三区精品电影| 国产精品99久久久久久有的能看| 亚洲电影自拍| 永久久久久久| 国产在线精品二区| 国产日韩欧美二区| 国产欧美日韩精品a在线观看| 欧美午夜精品久久久久久超碰| 欧美国产先锋| 欧美欧美午夜aⅴ在线观看| 欧美91视频| 欧美日本国产一区| 欧美日韩中文字幕日韩欧美| 欧美日韩国产成人精品| 欧美日韩高清在线一区| 欧美日韩不卡视频| 国产精品久久久久77777| 欧美视频亚洲视频| 国产精品分类| 国产农村妇女毛片精品久久麻豆 | 久久精品综合一区| 性欧美1819sex性高清| 亚洲欧美一区二区三区极速播放 | 亚洲欧美经典视频| 午夜在线一区二区| 久久精品一区| 亚洲电影免费观看高清| 欧美日韩不卡一区|