C#可以被命令行编译c代码成本地二进制代码么

22680人阅读
.NET(24)
这篇Blog好久没有更新了。最近一直在忙.NET Native相关的事情(主要是MCG),但是又因为保密的原因不能在Blog中提到。上个星期Build终于发布(可惜没有去成,team名额太少),我也终于可以谈下.NET Native的一些东西了,呵呵。
如果大家还没有看到之前的发布信息,可以去下面几个网址看看:
如果英文听力不错的话,可以听一下我们team principal dev lead的talk(其实他的英文比较难懂,速度快。。。):
这里简单讲一下.NET Native的基本架构,基本内容和上面那个talk其实差不多,只是简单给大家讲一下.NET Native的一些基本概念。如果大家有对某个部分具体感兴趣,也可以提出来,我尽量在我能力范围内解答(毕竟不是我一个人做的,呵呵)或者写新的Blog详细解释。
.NET Native和之前的NGEN有本质区别。NGEN实际上是把CLR运行时的数据结构和代码给一锅端(当然,这个是简化的说法,实际上比这个复杂)的放到最终的PE里面去了,运行的时候还是需要整个.NET Framework支持,而且不能避免JIT。.NET Native是全新的技术,整个.NET Framework经过refactoring重写,最终的runtime非常小,只有数百K,无需任何安装(除了mrt100.dll之外,大家可以理解成msvcrt.dll)。大部分的功能都从runtime中refactor到framework中作为C#代码或者作为toolchain一部分存在。一个典型的例子是:P/invoke原来是由CLR实现,使用C++和汇编编写。而现在是经由MCG这个工具接手,直接生成C#。最终.NET
Native生成的EXE/DLL是可以直接运行的机器码(通过C++编译器后端生成)。对了,有些朋友可能会问:我们是不是直接生成C++代码?答案是否定的。我们所使用的C++编译器后端接受IL作为输入,生成MDIL。
整个Toolchain(工具链)大致可以分为下面几个阶段:
App IL + FX -& MCG -& Interop.g.cs -& CSC -& Interop.dll -& Merge -& IL transform -& NUTC -& RhBind -& .EXE
第一步:将应用程序的IL代码和整个.NET Framework BCL的IL一起作为输入给MCG。MCG (Marshalling Code Generator)这一块主要是我在负责。这个工具负责检查程序和BCL中所有的Interop相关的类型,比如WinRT接口,P/Invoke,等等。MCG都会为之生成C#代码。这个C#代码是可以直接调试的,有兴趣的朋友可以F11试一下看看。C#代码的作用主要是替代Windows.WinMD中的WinRT类型定义,P/invoke定义,等等,添加各种类型的转换代码,比如字符串类型,RCW和CCW,等等,最终直接调用到本地代码。可能有些朋友会问道:为什么要生成C#?
原来的CLR是直接在运行时生成IL代码的,但是显然这个方法在.NET Native不太适用,而且IL代码很难调试。C#既方便大家调试,也方便我们快速的修改生成的代码,添加更多的功能。(写C++程序生成IL代码可是比较麻烦的,得人工算好stack的位置)
第二步:MCG生成的C#代码通过CSC编译,生成PE文件。这一步没啥可讲的。
第三步:这个PE文件被打包合并到应用程序和BCL,生成一个IL代码的集合。为下一步做好准备。
第四步:这个IL代码的集合会被经过若干的步骤处理,每个步骤都相对简单,只做一件事情。这些步骤的主要作用是提供原来CLR运行时提供的功能,最终的目的是使之最后的代码能够被C++最后编译。在原来桌面版本的CLR里面(也就是4.5里面的那个),很多功能是由Runtime来提供,比如Delegate.Invoke,比如interop。这些Transform的作用是对代码进行处理,把原来需要runtime实现的部分用实际代码替换掉。举个几个例子:
1. 当你在调用Windows.UI.Xaml.Controls.Button类型的时候,MCG也会生成一个对应的Button类型,然后IL Transform会将两者进行替换,这样程序调用的Button类型就是MCG生成的代码了。
2. 当你在进行Serialization和Deserialization的时候,IL Transform会调用另外一个工具SG来生成serialization/deserialization的C#代码,最终这些操作都有这些C#代码生成。
3. 你的程序多半不会用到整个BCL。IL Transform中会有一步叫做Dependency Reducer,使用类似GC的算法(mark-&sweep),去掉不需要的代码。MCG也和DR通力合作,减少不必要的interop代码生成。DR也会读取RD.XML文件,决定那些类型需要反射信息,那些不需要。RD.XML这一块我们还在改善之中,也希望大家多提宝贵意见。
其实呢,MCG其实也是IL Transform的一部分,只不过它实际上不Transform而已,而是直接生成C#。
第五步:NUTC对IL进行处理,生成MDIL。NUTC就是传说中的C++的编译器后端的一个特殊版本,优化什么的就靠它了。最后生成的MDIL接近机器码,但是也包含一些抽象的类型信息,需要进一步处理。
第六步:RhBind负责对MDIL进行处理,将里面和类型系统相关的信息生成代码,最后生成一个EXE。其实最终是一个EXE+DLL,实际的代码都在DLL中。EXE只是起到Bootstrap的作用。选用DLL的原因是我们需要支持作为Background Task在Broker里面加载。
几个我听到的常问的问题(如果有些答案过于“官方”,请谅解):
1. 你们最后是生成C++代码吗?
答:不生成。C++后端直接从IL转换成MDIL。
2. WPF支持吗?
答:暂时不支持。目前暂时只支持Windows Store Apps
3. 这个会支持桌面程序吗?
答:目前暂时只支持Windows Store Apps
4. 这个支持JIT吗?
答:目前.NET Native不支持JIT,所有代码都是编译时候生成。
5. 既然是本地机器码,为什么还可以支持类型反射(reflection)?
答:机器码和反射并不冲突,我们在PE文件中储存了额外的用于反射的信息,然后动态读取此信息进行调用。C++也可以支持反射(RTTI),只是不如.NET强大而已。
6.这个需要安装.NET Framework吗?
答:开发编译的时候需要,运行时不需要。
7.为什么不支持VB
答:VB本质上和C#都是生成IL,技术上非常类似。只是目前我们因为时间问题,暂只支持C#。
8.为什么启动运行速度会变快?
答:一方面归功于C++的优秀的编译器后端,一方面也因为runtime的重写和简化。
这次就大概讲这么多。欢迎大家试用一下.NET Native,去下面几个地方给我们提一下意见:
如果不想写英文的话(其实写中文也行),也可以直接在本blog留言。
.NET Native
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:634757次
积分:7638
积分:7638
排名:第2171名
原创:118篇
转载:11篇
评论:480条
(1)(1)(3)(2)(2)(2)(4)(1)(2)(3)(7)(4)(3)(2)(2)(3)(1)(1)(10)(9)(1)(1)(7)(11)(23)(7)(10)(5)(3)
() () () () () () () () () () () () () () () () () () ()C#版本控制 - C#教程 - 编程入门网
C#版本控制
版本控制(Versioning)主要是为了解决组件的版本不兼容的问题。版本兼容的方式有:
●源代码级兼容:依赖于旧版本的代码在重新编译之后能够与新版本兼容。
●二进制兼容:依赖于旧版本的应用程序无需重新编译就能与新版本兼容。
大多数语言根本不支持二进制级的版本兼容,其中许多在源代码级的兼容问题上也表现的不尽如人意。事实上,许多语言由于自身的缺陷,不改写客户代码就不可能实现组件的升级。
举个例子,假设基类的作者写了一个叫Base的类。在第一个版本中,类Base中没有包含方法F。一个叫Derived的类从Base中继承,并且声明了一个方法F。类Derived和类Base一同被交付客户使用,并且配置到许多客户机和服务器上。
// Author A
namespace A
public class Base //version 1
//Author B
namespace B
class Derived:A.Base
public virtual void F(){
System.Console.WriteLine(&Derived.F&);
到目前为止,程序的运行一切正常。然后,Base类的作者提供了一个新版本,给类Base添加了一个方法F。
//Author A
namespace A
public class Base //version 2
public virtual void F(){
//added in version 2
System.Console.WriteLine(&Base.F&);
新版本的Base应该和旧版本保持源代码级兼容和二进制级兼容。不幸的是,类Base中的新方法与类Derived中的F产生了混淆。Derived应该重载Base中的F吗?看上去不应该,因为Derived已经被编译,那时Base中甚至还没有F!但是,如果Derived中的F不重载Base中的F,而它又必须符合基类Base的声明,可是在写Derived类时还不存在该声明。比如某种情况下,Base中的F可能要求被重载。
在解决版本问题时,C#要求开发人员清楚地表达他们的意图。在原始代码中,类Base不包括方法F,所以不存在什么问题。Derived中的F是作为一个新方法,而不是重载基类中的方法。
//Author A
namespace A
public class Base
//Author B
namespace B
class Derived:A.Base
public virtual void F(){
System.Console.WriteLine(&Derived.F&);C#实现将记事本中的代码编译成可执行文件的方法_C#教程_ThinkSAAS
C#实现将记事本中的代码编译成可执行文件的方法
C#实现将记事本中的代码编译成可执行文件的方法
内容来源: 网络
本文实例讲述了C#实现将记事本中的代码编译成可执行文件的方法,运行环境为VS2012,具体方法如下:1、在记事本中编写如下代码:using Snamespace HelloWorld{
public class Program
static void Main(string[] args)
Console.WriteLine("Hello,World");
Console.ReadKey();
}}2、保存为HelloWorld.txt,位置在F:学习练习NET之美学习练习NET之美。3、打开开发人员命令提示。4、输入如下命令5、最终把HelloWorld.txt转换成了Hi.exe可执行文件。
PHP开发框架
开发工具/编程工具
服务器环境
ThinkSAAS商业授权:
ThinkSAAS为用户提供有偿个性定制开发服务
ThinkSAAS将为商业授权用户提供二次开发指导和技术支持
让ThinkSAAS更好,把建议拿来。
开发客服微信

我要回帖

更多关于 如何编译c源代码 的文章

 

随机推荐