• <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>
            隨筆-341  評(píng)論-2670  文章-0  trackbacks-0
                在制作GacUI讀pdb生成代碼的過(guò)程中,感受到了C++語(yǔ)言設(shè)計(jì)和dll的需求之間的鴻溝。對(duì)于一個(gè)充分利用了C++各種功能的類庫(kù)來(lái)說(shuō),制作成dll具有非常大的困難,特別是在函數(shù)返回POD(Plain Old Data)的引用,和輸入輸出帶有泛型的類上面。所以現(xiàn)在還是決定以源代碼的方式來(lái)發(fā)布GacUI。但是pdb生成代碼并沒有白做,因?yàn)榉瓷溥€是存在的。但是因?yàn)镚acUI一共有48000行代碼,80多個(gè)源代碼文件,直接發(fā)布使用起來(lái)總是不方便。所以我寫了個(gè)小工具,根據(jù)xml的配置來(lái)將源代碼合并成少數(shù)幾個(gè)比較大的代碼文件。這樣使用的時(shí)候,只需要直接把幾個(gè)cpp拖進(jìn)工程里面,就可以使用了。而且根據(jù)之前發(fā)布的一個(gè)投票,似乎大家也最喜歡這種方法。因此這次的決定,僅僅刪掉了作為backup plan的dll方法。

                這里我給出小工具的代碼和配置文件。這個(gè)配置文件是基于GacUI做出來(lái)的,不過(guò)大家可以修改它,以便用于自己的工程上面:
            <?xml version="1.0" encoding="utf-8" ?>
            <codegen>
              
            <projects>
                
            <project path="..\..\..\GacUISrc\GacUISrc.vcxproj" />
              
            </projects>
              
            <categories>
                
            <category name="vlpp" pattern="\Library\"/>
                
            <category name="gacui" pattern="\GacUILibrary\">
                  
            <except filename="GacUI_WinMain.cpp" />
                  
            <except filename="GuiTypeDescriptorImpHelper.cpp" />
                  
            <except filename="GuiTypeDescriptorImpProvider_codegen.cpp" />
                
            </category>
              
            </categories>
              
            <output path="..\..\..\GacUILibraryExternal\">
                
            <codepair category="vlpp" filename="Vlpp" />
                
            <codepair category="gacui" filename="GacUI" />
                
            <header source="..\..\..\GacUILibrary\GacUI.h" filename="GacUIIncludes" />
              
            </output>
            </codegen>

                在這里面,project包含了用于開發(fā)這個(gè)工程的所有VC++2010的工程文件的地址,然后使用category對(duì)他們進(jìn)行分類(pattern是文件全名的某個(gè)部分),最后對(duì)每一個(gè)部分生成一對(duì)cpp和h。在最后生成代碼對(duì)的時(shí)候,如果源代碼從一開始就存在依賴關(guān)系的話,那么在代碼對(duì)的h文件里面,會(huì)包含依賴的代碼對(duì)的h。在這里,vlpp是獨(dú)立的,而gacui依賴了vlpp,所以gacui.h將會(huì)#include"vlpp.h",而cpp只include自己的h文件。output里面除了codepair以外還有header,header是不參與codepair計(jì)算的,純粹為了生成“可以省事直接include”的頭文件。在這個(gè)例子里面,GacUIIncludes.h將會(huì)包含完整的GacUI.h和一部分的Vlpp.h,而且是可以通過(guò)編譯的。

             驅(qū)動(dòng)器 E 中的卷沒有標(biāo)簽。
             卷的序列號(hào)是 
            9614-79B9

             E:\Codeplex\vlpp\Workspace\Tools\Release\SideProjects\GacUISrc\GacUILibraryExternal 的目錄

            2012/02/29  21:42    <DIR>          .
            2012/02/29  21:42    <DIR>          ..
            2012/02/29  21:42                 0 dir.txt
            2012/02/29  21:18           677,987 GacUI.cpp
            2012/02/29  21:18           304,231 GacUI.h
            2012/02/29  21:18           481,551 GacUIIncludes.h
            2012/02/29  21:18            69,348 Vlpp.cpp
            2012/02/29  21:18           310,126 Vlpp.h
                           
            6 個(gè)文件      1,843,243 字節(jié)
                           
            2 個(gè)目錄 166,357,680,128 可用字節(jié)

               在生成的時(shí)候,生成器將會(huì)閱讀代碼本身,然后獲取#include "path",然后對(duì)他們的關(guān)系進(jìn)行處理。這個(gè)工具的代碼如下:
            using System;
            using System.Collections.Generic;
            using System.Linq;
            using System.Text;
            using System.IO;
            using System.Xml.Linq;
            using System.Text.RegularExpressions;

            namespace Codegen
            {
                
            class Program
                {
                    
            static string[] GetCppFiles(string projectFile)
                    {
                        
            string np = @"http://schemas.microsoft.com/developer/msbuild/2003";
                        XDocument document 
            = XDocument.Load(projectFile);
                        
            return document
                            .Root
                            .Elements(XName.Get(
            "ItemGroup", np))
                            .SelectMany(e 
            => e.Elements(XName.Get("ClCompile", np)))
                            .Select(e 
            => Path.GetFullPath(Path.GetDirectoryName(projectFile) + "\\" + e.Attribute("Include").Value))
                            .ToArray();
                    }

                    
            static Dictionary<stringstring[]> CategorizeCodeFiles(XDocument config, string[] files)
                    {
                        Dictionary
            <stringstring[]> categorizedFiles = new Dictionary<stringstring[]>();
                        
            foreach (var e in config.Root.Element("categories").Elements("category"))
                        {
                            
            string name = e.Attribute("name").Value;
                            
            string pattern = e.Attribute("pattern").Value.ToUpper();
                            
            string[] exceptions = e.Elements("except").Select(x => x.Attribute("filename").Value.ToUpper()).ToArray();
                            categorizedFiles.Add(
                                name,
                                files
                                    .Where(f 
            => f.ToUpper().Contains(pattern))
                                    .Where(f 
            => !exceptions.Contains(Path.GetFileName(f).ToUpper()))
                                    .ToArray()
                                    );
                        }
                        
            foreach (var a in categorizedFiles.Keys)
                        {
                            
            foreach (var b in categorizedFiles.Keys)
                            {
                                
            if (a != b)
                                {
                                    
            if (categorizedFiles[a].Intersect(categorizedFiles[b]).Count() != 0)
                                    {
                                        
            throw new ArgumentException();
                                    }
                                }
                            }
                        }
                        
            return categorizedFiles;
                    }

                    
            static Dictionary<stringstring[]> ScannedFiles = new Dictionary<stringstring[]>();
                    
            static Regex IncludeRegex = new Regex(@"^\s*\#include\s*""(?<path>[^""]+)""\s*$");
                    
            static Regex IncludeSystemRegex = new Regex(@"^\s*\#include\s*\<(?<path>[^""]+)\>\s*$");

                    
            static string[] GetIncludedFiles(string codeFile)
                    {
                        codeFile 
            = Path.GetFullPath(codeFile).ToUpper();
                        
            string[] result = null;
                        
            if (!ScannedFiles.TryGetValue(codeFile, out result))
                        {
                            List
            <string> directIncludeFiles = new List<string>();
                            
            foreach (var line in File.ReadAllLines(codeFile))
                            {
                                Match match 
            = IncludeRegex.Match(line);
                                
            if (match.Success)
                                {
                                    
            string path = match.Groups["path"].Value;
                                    path 
            = Path.GetFullPath(Path.GetDirectoryName(codeFile) + @"\" + path).ToUpper();
                                    
            if (!directIncludeFiles.Contains(path))
                                    {
                                        directIncludeFiles.Add(path);
                                    }
                                }
                            }

                            
            for (int i = directIncludeFiles.Count - 1; i >= 0; i--)
                            {
                                directIncludeFiles.InsertRange(i, GetIncludedFiles(directIncludeFiles[i]));
                            }
                            result 
            = directIncludeFiles.Distinct().ToArray();
                            ScannedFiles.Add(codeFile, result);
                        }
                        
            return result;
                    }

                    
            static string[] SortDependecies(Dictionary<stringstring[]> dependeicies)
                    {
                        var dep 
            = dependeicies.ToDictionary(p => p.Key, p => new HashSet<string>(p.Value));
                        List
            <string> sorted = new List<string>();
                        
            while (dep.Count > 0)
                        {
                            
            bool found = false;
                            
            foreach (var p in dep)
                            {
                                
            if (p.Value.Count == 0)
                                {
                                    found 
            = true;
                                    sorted.Add(p.Key);
                                    
            foreach (var q in dep.Values)
                                    {
                                        q.Remove(p.Key);
                                    }
                                    dep.Remove(p.Key);
                                    
            break;
                                }
                            }
                            
            if (!found)
                            {
                                
            throw new ArgumentException();
                            }
                        }
                        
            return sorted.ToArray();
                    }

                    
            static void Combine(string[] files, string outputFilename, HashSet<string> systemIncludes, params string[] externalIncludes)
                    {
                        
            try
                        {
                            
            using (StreamWriter writer = new StreamWriter(new FileStream(outputFilename, FileMode.Create), Encoding.Default))
                            {
                                writer.WriteLine(
            "/***********************************************************************");
                                writer.WriteLine(
            "THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY");
                                writer.WriteLine(
            "DEVELOPER: 陳梓瀚(vczh)");
                                writer.WriteLine(
            "***********************************************************************/");
                                
            foreach (var inc in externalIncludes)
                                {
                                    writer.WriteLine(
            "#include \"{0}\"", inc);
                                }

                                
            foreach (var file in files)
                                {
                                    writer.WriteLine(
            "");
                                    writer.WriteLine(
            "/***********************************************************************");
                                    writer.WriteLine(file);
                                    writer.WriteLine(
            "***********************************************************************/");
                                    
            foreach (var line in File.ReadAllLines(file, Encoding.Default))
                                    {
                                        Match match 
            = null;

                                        match 
            = IncludeSystemRegex.Match(line);
                                        
            if (match.Success)
                                        {
                                            
            if (systemIncludes.Add(match.Groups["path"].Value.ToUpper()))
                                            {
                                                writer.WriteLine(line);
                                            }
                                        }
                                        
            else
                                        {
                                            match 
            = IncludeRegex.Match(line);
                                            
            if (!match.Success)
                                            {
                                                writer.WriteLine(line);
                                            }
                                        }
                                    }
                                }
                            }
                            Console.WriteLine(
            "Succeeded to write: {0}", outputFilename);
                        }
                        
            catch (Exception)
                        {
                            Console.WriteLine(
            "Failed to write: {0}", outputFilename);
                        }
                    }

                    
            static void Combine(string inputFilename, string outputFilename, params string[] externalIncludes)
                    {
                        HashSet
            <string> systemIncludes = new HashSet<string>();
                        
            string[] files = GetIncludedFiles(inputFilename).Concat(new string[] { inputFilename }).Distinct().ToArray();
                        Combine(files, outputFilename, systemIncludes, externalIncludes);
                    }

                    
            static void Main(string[] args)
                    {
                        
            // load configuration
                        XDocument config = XDocument.Load("CodegenConfig.xml");
                        
            string folder = Path.GetDirectoryName(typeof(Program).Assembly.Location) + "\\";

                        
            // collect project files
                        string[] projectFiles = config.Root
                            .Element(
            "projects")
                            .Elements(
            "project")
                            .Select(e 
            => Path.GetFullPath(folder + e.Attribute("path").Value))
                            .ToArray();

                        
            // collect code files
                        string[] unprocessedCppFiles = projectFiles.SelectMany(GetCppFiles).Distinct().ToArray();
                        
            string[] unprocessedHeaderFiles = unprocessedCppFiles.SelectMany(GetIncludedFiles).Distinct().ToArray();

                        
            // categorize code files
                        var categorizedCppFiles = CategorizeCodeFiles(config, unprocessedCppFiles);
                        var categorizedHeaderFiles 
            = CategorizeCodeFiles(config, unprocessedHeaderFiles);
                        var outputFolder 
            = Path.GetFullPath(folder + config.Root.Element("output").Attribute("path").Value);
                        var categorizedOutput 
            = config.Root
                            .Element(
            "output")
                            .Elements(
            "codepair")
                            .ToDictionary(
                                e 
            => e.Attribute("category").Value,
                                e 
            => Path.GetFullPath(outputFolder + e.Attribute("filename").Value
                                ));

                        
            // calculate category dependencies
                        var categoryDependencies = categorizedCppFiles
                            .Keys
                            .Select(k 
            =>
                                {
                                    var headerFiles 
            = categorizedCppFiles[k]
                                        .SelectMany(GetIncludedFiles)
                                        .Distinct()
                                        .ToArray();
                                    var keys 
            = categorizedHeaderFiles
                                        .Where(p 
            => p.Value.Any(h => headerFiles.Contains(h)))
                                        .Select(p 
            => p.Key)
                                        .Except(
            new string[] { k })
                                        .ToArray();
                                    
            return Tuple.Create(k, keys);
                                })
                            .ToDictionary(t 
            => t.Item1, t => t.Item2);

                        
            // sort categories by dependencies
                        var categoryOrder = SortDependecies(categoryDependencies);
                        Dictionary
            <string, HashSet<string>> categorizedSystemIncludes = new Dictionary<string, HashSet<string>>();

                        
            // generate code pair header files
                        foreach (var c in categoryOrder)
                        {
                            
            string output = categorizedOutput[c] + ".h";
                            List
            <string> includes = new List<string>();
                            
            foreach (var dep in categoryDependencies[c])
                            {
                                includes.AddRange(categorizedSystemIncludes[dep]);
                            }
                            HashSet
            <string> systemIncludes = new HashSet<string>(includes.Distinct());
                            categorizedSystemIncludes.Add(c, systemIncludes);
                            Combine(
                                categorizedHeaderFiles[c],
                                output,
                                systemIncludes,
                                categoryDependencies[c]
                                    .Select(d 
            => Path.GetFileName(categorizedOutput[d] + ".h"))
                                    .ToArray()
                                );
                        }

                        
            // generate code pair cpp files
                        foreach (var c in categoryOrder)
                        {
                            
            string output = categorizedOutput[c];
                            
            string outputHeader = Path.GetFileName(output + ".h");
                            
            string outputCpp = output + ".cpp";
                            HashSet
            <string> systemIncludes = categorizedSystemIncludes[c];
                            Combine(
                                categorizedCppFiles[c],
                                outputCpp,
                                systemIncludes,
                                outputHeader
                                );
                        }

                        
            // generate header files
                        var headerOutput = config.Root
                            .Element(
            "output")
                            .Elements(
            "header")
                            .ToDictionary(
                                e 
            => Path.GetFullPath(folder + e.Attribute("source").Value),
                                e 
            => Path.GetFullPath(outputFolder + e.Attribute("filename").Value)
                                );
                        
            foreach (var o in headerOutput)
                        {
                            Combine(o.Key, o.Value 
            + ".h");
                        }
                    }
                }
            }

                代碼已經(jīng)checkin在了Vczh Library++3.0(Tools\Release\SideProjects\GacUISrc\GacUISrc.sln)下面,里面也包含了生成后的代碼。
            posted on 2012-02-29 05:34 陳梓瀚(vczh) 閱讀(4012) 評(píng)論(9)  編輯 收藏 引用 所屬分類: GacUI

            評(píng)論:
            # re: 最終還是決定直接以源代碼方式發(fā)布GacUI了 2012-02-29 07:32 | Exoticknight
            只看到開源二字就應(yīng)該支持,雖然我暫時(shí)不懂C++  回復(fù)  更多評(píng)論
              
            # re: 最終還是決定直接以源代碼方式發(fā)布GacUI了 2012-02-29 09:17 | Zblc
            強(qiáng)烈支持 拭目以待 = =+   回復(fù)  更多評(píng)論
              
            # re: 最終還是決定直接以源代碼方式發(fā)布GacUI了 2012-02-29 18:29 | 春秋十一月
            本想幫你的腳本弄個(gè)benchmark, 和lua之類的對(duì)比一下速度。無(wú)奈那么多數(shù)學(xué)函數(shù)里,就木有找到sqrt函數(shù),太杯具了。可以軟實(shí)現(xiàn)sqrt,但結(jié)果肯定不公平,無(wú)奈只得放棄。  回復(fù)  更多評(píng)論
              
            # re: 最終還是決定直接以源代碼方式發(fā)布GacUI了[未登錄] 2012-02-29 21:15 | 陳梓瀚(vczh)
            @春秋十一月
            一定要sqrt?  回復(fù)  更多評(píng)論
              
            # re: 最終還是決定直接以源代碼方式發(fā)布GacUI了 2012-02-29 22:58 | phoenixbing
            不容易,真不容易。48000行代碼,80多個(gè)源代碼文件  回復(fù)  更多評(píng)論
              
            # re: 最終還是決定直接以源代碼方式發(fā)布GacUI了 2012-02-29 22:58 | phoenixbing
            不能支持你更多  回復(fù)  更多評(píng)論
              
            # re: 最終還是決定直接以源代碼方式發(fā)布GacUI了 2012-03-01 04:42 | bennycen
            火速前來(lái)參拜Orz  回復(fù)  更多評(píng)論
              
            # re: 最終還是決定直接以源代碼方式發(fā)布GacUI了[未登錄] 2012-03-01 09:40 | 潘孫友
            還是以源碼方式提供吧,最直接最給力了!  回復(fù)  更多評(píng)論
              
            # re: 最終還是決定直接以源代碼方式發(fā)布GacUI了 2012-03-01 17:34 | 空明流轉(zhuǎn)
            @春秋十一月
            SQRT其實(shí)沒啥比較的價(jià)值,因?yàn)檫@個(gè)不是什么常用的函數(shù),如果以數(shù)學(xué)為主導(dǎo)的腳本,那肯定有匯編實(shí)現(xiàn),如果是以邏輯為主導(dǎo)的,那一般都是轉(zhuǎn)發(fā)CRT的SQRT了。  回復(fù)  更多評(píng)論
              
            久久妇女高潮几次MBA| 精品免费久久久久国产一区| 国产午夜电影久久| 婷婷久久久亚洲欧洲日产国码AV| 久久久久久av无码免费看大片| 精品久久无码中文字幕| 亚洲AV无码久久精品成人| 久久这里的只有是精品23| 久久精品国产国产精品四凭| 亚洲成色999久久网站| 久久se精品一区精品二区| 久久久久久九九99精品| 无码人妻久久一区二区三区免费丨| 亚洲国产精品狼友中文久久久| 国产99久久久久久免费看| 久久99精品国产麻豆宅宅| 999久久久免费精品国产| 日韩精品久久无码中文字幕| 亚洲中文精品久久久久久不卡| 一本色道久久88综合日韩精品| 亚洲精品NV久久久久久久久久| 久久久这里有精品中文字幕| 久久久精品波多野结衣| 久久性生大片免费观看性| 思思久久好好热精品国产| 综合人妻久久一区二区精品| 亚洲精品蜜桃久久久久久| 久久精品中文字幕无码绿巨人| 久久久亚洲欧洲日产国码aⅴ| 久久超碰97人人做人人爱| 国产成人久久精品区一区二区| 久久久国产精品网站| 蜜桃麻豆www久久国产精品| 国产99久久久国产精品小说| 国产AV影片久久久久久| 久久99精品久久久久久9蜜桃| 亚洲国产精品成人久久蜜臀 | 69国产成人综合久久精品| 久久九九全国免费| 欧美亚洲国产精品久久久久| 久久久婷婷五月亚洲97号色|