首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

现在小弟我是很反感C++这个语言

2012-11-11 
现在我是很反感C++这个语言应当讲我现在是很不喜欢C这个语言。不仅仅语言复杂,这其实倒也无所谓,但问题是:C

现在我是很反感C++这个语言

应当讲我现在是很不喜欢C++这个语言。

不仅仅语言复杂,这其实倒也无所谓,但问题是:C++是“一次编写,到处编链(生成),各种编链不过”,这就是C++的真正特点。这两天弄那个Teigha的CAD文件处理库,很装x闭源的库(所以C++也更应提倡开源,开源你去解决编译问题,闭源你就去解决可能永远解决不了的链接问题去吧)加一些很装x的例子程序写了一大坨,每种平台和配置都做一个包,总大小好几个G,拿下来去升级整合原先的调用程序,折腾了两天最后运行还通不过。这种情况只要遇到调用第三方库就总会遇到,而且每次遇到就算情况再相似都会无谓耗费大量时间。所以可以讲C++是一种开发效率非常低下的语言。无尽的咒骂。。。

最终除了很多冗繁的各类编译链接设置,这个问题最终是关于Unmanaged C++库(需要Windows CRT库)和C#应用程序side-by-side链接问题。

我的场景是(也是一个比较经典的):C#应用调用C++/CLI的类似Wrapper的库,而后者包含一些普通C++的动态连接库。而每次运行总会提示一些错误主要是“MSVCR90.DLL”无法找到,这个错误可以忽略,但之后的运行行为则不确定,一个旧版本的Teigha库可以正常运行(但也有一些报错),另一些版本则无法正常输出结果。有趣的是如果用一个C++/CLI做的managed的等价应用程序去调用,则不会有任何错误。一个简单的栈检查发现(也在意料之中),C++/CLI的应用的调用入口不存在managed和unmanaged的转移(C++在Windows(也许是几乎所有操作系统)下的确是名副其实的一等公民),这很有可能是造成这种执行行为差异的原因。

我尝试做了一个纯C/C++的DLL,然后其中做一些类似于那个Wrapper库做的简单的初始化工作(会导致那个MSVCR90.DLL无法找到错误)并暴露纯C接口(这是P/Invoke的规定),然后由C#去调用之,发现错误仍旧出现,说明这和C#对Native的互联操作方式无关。

而且解决这个问题的办法一般总是为C# App配置一个manifest。

有一些比较好的解答如:http://stackoverflow.com/questions/8039586/pinvoke-fails-because-of-dlls-dependent-on-other-sxs-dlls;只是这里要对文件版本等参数根据系统中存在的进行调整(要到Windows\winsxs目录下去搜索MSVCR90.DLL,然后根据文件夹名称的提示改写,注意public key token是不变的(也在文件夹名中可看出)。

在根据步骤配置完manifest之后,我发现我仍然得到这些错误,非常恼怒,我尝试对C++ Wrapper工程也引入manifest,也无效。偶然我将配置改为Release,问题解决,运行一切正常,包括在那个DLL遗失错误之后的更严重运行错误也消失了(我估计对纯.NET接入的程序只能在Release模式不依赖那个debug版本CRT的情形下执行)。

然后我最后还得测试一下,如果去掉这个manifest会怎样,结果是运行失常,由此最终确定C# App需要这个新增的manifest。

另外在Teigha本身提供的.NET版本的库和实例工程中看,它的app并没有定制manifest,我估计原因是那个工程是在VS2008中,于是默认manifest或生成自动加入了这个VS2008 C++的运行时库路径。但它的功德是它只包含了Release版本,所以提示了我回到Release模式下去看看状况。

还是放松一下,让C#来平复一下被C++搞毛的心情,弄了一个用来分账单的小程序。多么优雅,写写这种代码被C++折去的寿命也能修补几年回来。

using System;using System.Collections.Generic;using System.Linq;namespace ConsoleApplication1{    class Program    {        struct UsageSegment : IComparable<UsageSegment>        {            public DateTime Start;  // inclusive            public DateTime End;    // inclusive            public decimal Units;   // number of persons            public decimal TotalUnits            {                get { return ((decimal) (End - Start).TotalDays + 1)*Units; }            }            public int CompareTo(UsageSegment other)            {                if (End < other.Start) return -1;                return Start > other.End ? 1 : 0;            }        }        class PersonalUsage        {            public DateTime MinDate { get; private set; }            public DateTime MaxDate { get; private set; }            public decimal TotalUnits            {                get                {                    if (_dirty)                    {                        _totalUnits = 0;                        foreach (var seg in _segments)                        {                            _totalUnits += seg.TotalUnits;                        }                    }                    return _totalUnits;                }            }            private readonly List<UsageSegment> _segments = new List<UsageSegment>();            public PersonalUsage()            {                MinDate = DateTime.MaxValue;                MaxDate = DateTime.MinValue;            }            public string[] GetDescription()            {                var res = new string[_segments.Count];                var i = 0;                foreach (var seg in _segments)                {                    res[i++] += string.Format("{0} Users: {1} to {2}",                                         seg.Units, seg.Start.ToShortDateString(), seg.End.ToShortDateString());                }                return res;            }            public PersonalUsage Add(DateTime start, DateTime end, decimal units = 1)            {                if (start > end)                {                    throw new Exception("End date is not allowed to be earlier than start");                }                var newSeg = new UsageSegment {Start = start, End = end, Units = units};                var index = _segments.BinarySearch(newSeg);                if (index >= 0)                {                    // overlapping                    throw new Exception("Current implementation doesn't allow overlapping");                }                index = -index - 1;                _segments.Insert(index, newSeg);                if (start < MinDate) MinDate = start;                if (end > MaxDate) MaxDate = end;                _dirty = true;                return this;            }            private bool _dirty;            private decimal _totalUnits;        }        class PersonDictionary : Dictionary<string, PersonalUsage>, IDictionary<string, PersonalUsage>        {            public new PersonalUsage this[string key]            {                get                {                    if (!ContainsKey(key))                    {                        base[key] = new PersonalUsage();                    }                    return base[key];                }                set { base[key] = value; }            }        }        class UsageSplitter        {            public IDictionary<string, PersonalUsage> Persons { get; private set; }            public decimal TotalAmountDue { private get; set; }            public UsageSplitter()            {                Persons = new PersonDictionary();            }            public void MakeSummary()            {                var summedUnits = Persons.Sum(x => x.Value.TotalUnits);                decimal summedPayment = 0;                var minDate = DateTime.MaxValue;                var maxDate = DateTime.MinValue;                Console.WriteLine("       Name         |               Description              | Usage | Payment ");                foreach (var p in Persons)                {                    var val = p.Value;                    var desc = val.GetDescription();                    var payment = Math.Round( TotalAmountDue * val.TotalUnits * 100 / summedUnits) / 100;                    summedPayment += payment;                    Console.WriteLine("{0,-20}|{1,-40}|{2,7}|{3,9:0.00}", p.Key, desc[0], val.TotalUnits, payment);                    for (var i = 1; i < desc.Length; i++)                    {                        Console.WriteLine("                    |{0,-40}|       |", desc[i]);                    }                    if (val.MinDate < minDate) minDate = val.MinDate;                    if (val.MaxDate > maxDate) maxDate = val.MaxDate;                }                Console.WriteLine("     [Total]        |{0,-40}|{1,7}|{2,9}",                     string.Format("Usage from {0} to {1}", minDate.ToShortDateString(), maxDate.ToShortDateString()),                    summedUnits, summedPayment);            }        }        static void SampleReport()        {            var startDate = new DateTime(2012, 7, 21);            var endDate = new DateTime(2012, 10, 25);            var split = new UsageSplitter {TotalAmountDue = 1777.24m};            var normal = new PersonalUsage();            normal.Add(startDate, endDate);            split.Persons["Li"] = normal;            split.Persons["Hou"] = normal;            split.Persons["Fulei"] = normal;            split.Persons["Max"].Add(new DateTime(2012, 8, 20), endDate);            split.Persons["Jiale"].Add(new DateTime(2012, 7, 23), endDate);            split.Persons["Sama"].Add(new DateTime(2012, 9, 1), endDate, 2);            split.Persons["Linc"].Add(startDate, new DateTime(2012, 10, 12)).Add(new DateTime(2012, 10, 13), endDate, 2);            split.Persons["Shane"].Add(startDate, new DateTime(2012, 8, 9));            split.Persons["Shane2"].Add(startDate, new DateTime(2012, 8, 9));            split.MakeSummary();        }        static void Main()        {            SampleReport();        }    }}


热点排行