Electronic Joint Business

Solution for E-Business

c#

编写一个 Commodore 64 模拟器

Commodor 64 (C64) 是 FC(Family Computer 俗称任天堂红白机)使用的微处理器,本文详细介绍如何用 C# 来实现一个 Commodore 64 模拟器。1

这个模拟器性能不太好,这主要是因为该仿真是基于时钟周期以及驱动器的实现等等代码实现方式。后来由于某些原因,我用 C++ 重新实现了该模拟器,这使得性能大大提升。这个结果促使我最终放弃了 C# 实现,因为不值得因为语言的限制来浪费时间与精力,我打算写篇文章来讨论这个问题。

虽然 C# 版有这样那样的缺失和问题,不过它仍适合作为理解仿真概念的基础。

在这篇文章中,我不想解释实际硬件是如何工作的。网上可以找到关于此话题的大量资源。这里我将主要关注如何进行仿真及其具体实现。

你想编译并运行该模拟器,建议先阅读一下关于 ROM 文件的小节。

>>> 阅读全文

 

, ,

.NET 编译平台 (Roslyn) 概述

文章评价:
一直以来,编译器都按黑盒的方式运作 — 这头放入源代码,中间部分施展魔法,在另一头就会生成目标文件或程序集。当编译器施展魔法时,它建立了对代码的深刻理解,但这些知识除了实现编译器的巫师外,旁人无法掌握。一旦生成编译输出,这些信息就被彻底忘却。几十年来,这种方式一直运作良好,但现在却不能满足需要了。

如今为了提高生产力, 人们越来越依赖于集成开发环境(IDE)所提供的智能感知、重构、智能重命名、 “查找所有引用” 和 “转到定义” 等功能。我们用代码分析工具来改善代码质量,用代码生成器来协助代码构建。想要让这些工具更聪明,就需要它们能更多地访问编译器,同时也需要对编译器中深厚的代码处理知识有更多的了解。

这就是 .NET 编译器平台(“Roslyn”)的核心使命:打开黑盒让工具和用户可以分享编译器处理代码时的大量信息。与 “源代码—目标文件”的直译方式不同,Roslyn 使编译器成为平台,这意味着工具和应用程序可以通过 API 来处理代码相关的任务。

将编译器过渡到平台,这大大降低了构建代码相关(code focused)工具与程序的门槛,在许多方面推动了创新,包括:元编程、代码生成、代码转化、C#\VB 的交互式使用、领域特定语言内嵌 C#\VB 等等。

在 .NET 编译器平台 (“Roslyn”) SDK 预览版中包括了最新的语言对象模型,可用于代码生成、代码分析与重构。我们还包括了一些 API 草稿,以便在后续的版本中实现支持脚本、C#\VB的交互式使用。本文是对 .NET 编译器平台(“Roslyn”)的概念性描述,更多情况可以参考预览版 SDK 中的演示与示例。

>>> 阅读全文

 

, , , , , , , ,

通过 C# 使用 ZeroMQ (二) 多段式消息,JSON 和同步发布/订阅模式

文章评价:

这是该系列文章的第二部分。在这部分文章中,我们会讨论 ZeroMQ 所能发送和接收的两大类消息,并且如何用 JSON 来格式化消息。我们还会学习 如何使用轮询 (polling) 机制。在文章的最后,我们举例说明什么是同步发布/订阅模式。

ZeroMQ消息
ZeroMQ 套接字可以发送或者接受单段式消息(single-part)或多段式消息(multi-part)。

单段式消息
所谓单段式消息,就是一个消息只包含一帧。所谓帧是一个字节数组,其长度可以零以上的数值。在 ZeroMQ 参考手册中,帧也被叫做“消息段 message parts”。

举个单段式消息的例子,就比如说上一篇文章中我们发送/接收的所有消息都是单段式消息。在发送和接收的操作中,我们使用的是字符串,而字符串实质也是一个字节数组。

>>> 阅读全文

 

, , , ,

通过 C# 使用 ZeroMQ (一) ZeroMQ 通讯模式

文章评价:
ZeroMQ (也拼写作 ØMQ、 0MQ 或 ZMQ) 是个非常轻量级的开源消息队列软件。它没有独立的服务器,消息直接从一个应用程序被发送到另一个应用程序。ZeroMQ 的学习和应用也非常简单,它只有一个 C++ 编写成的单个库文件 libzmq.dll, 可以链接到任何应用程序中。如果要在 .NET 环境中使用,我们需要用到一个 C# 编写的名为 clrzmq.dll 包装库。

ZeroMQ 可以在 Windows、 OS X 和 Linux 等多种操作系统上运行, C、 C++、 C#、 Java、 Python 等语言都可以编写 ZeroMQ 应用程序…这使得不同平台上的不同应用程序之间可以相互通讯。

ZeroMQ 的核心
ZeroMQ 的主要部分是套接字 Socket,不过它并未直接使用传统的套接字,而是在传统的套接字 API上提供了一个抽象层,这让用户从复杂和重复的编程任务中解脱出来。ZeroMQ 支持多种类型的套接字 (类型被定义为套接字自身的一个属性)。发送端和接收端的套接字类型组合造就了多种不同的通信模式,本文的后面我们会涉及到这一部分。

异步通讯
ZeroMQ 提供了异步通讯方式,这意味着即使在设置或关闭套接字连接、重新连接或进行消息传递的时候,应用程序都不会被阻塞。与程序正常任务处理并行的,这些操作由 ZeroMQ 自身在后台线程中进行管理。在需要时,ZeroMQ 会自动将消息 (无论是发件端或接受端) 放入队列中, 这一过程相当智能,消息会被推送到离接收端尽可能近的队列中。

传输协议
ZeroMQ 支持四类传输协议。每种传输协议由地址字符串来定义,该字符串由两部分组成:transport://endpoint。传输(transport) 部分指定了所使用的底层传输协议,端点(endpoint) 部分的格式则随着使用的协议而有所不同,具体如下:

>>> 阅读全文

 

, , , , ,

Windows Runtime中的异步模式

文章评价: 原文
Windows Runtime 提供了一套一致的模式来创建和管理异步操作。

下面的内容介绍了 Windows Runtime 中的异步编程(asynchronous programming),例子包括了 Javascript,C#,Visual Basic 和 Visual C++。

异步编程的好处
由于从 Windows Runtime 的异步编程模型中获益,Metro风格应用总是能对用户的输入及时做出响应。你可以运行费时的任务而不需阻塞 UI 线程,你可以在稍后才获得任务返回的结果。你可以取消任务,也可以当任务在后台运行时获得进度通知。你无需显示地管理线程或者直接和底层的并发(concurrence)实现打交道。

Windows Runtime 的许多特性以异步函数的形式呈现,比如 MediaCapture 和 StorageFile。作为约定,异步函数的名称以“Async”结尾,表明其执行可能发生在调用返回之后。

在 Metro 风格应用中使用异步API,代码可用一致的方法使用非阻塞调用。如果在用户的 API 里实现了异步模式,调用者就可以理解并按预知的形式使用你的代码。Windows Runtime 以贴近每种语言自身的方式提供了异步模式。见下表:

>>> 阅读全文

 

, , , , , , ,

Nemerle语法指南 之二

在本章中,我们会介绍一些 Nemerle 中如何定义类等等面向对象的元素,它和 C#、Java 或者 C++ 有些类似,但是略有区别。 同时,我们也会关注循环和一些简单的宏。

类的定义
我们不再介绍什么是类,关于这个问题,你可以参考任何一种面向对象的语言。在 Nemerle,关键字class用来定义一个类,基本格式是

class MyClass {
  // something inside
}

在类中可以定义很多实体,这些实体可以用访问修饰符或者其他修饰符来描述。

修饰符Modifiers
Nemerle 中有许多修饰符,最常见莫过于public, static和mutable。

我们将首先看一下访问修饰符。修饰符指定了其他类访问指定实体的方式。访问修饰符可以修饰类中定义的任何一个实体,默认为private。而public和interal则可用以修饰类,默认是internal,这些修饰符的含义如下:

>>> 阅读全文

 

, ,

Nemerle语法指南 之一

Nemerle 是.NET家族中的新丁,是 Microsoft 的研究项目之一,它由Wrocław大学的Kamil Skalski、Michał Moskal、Prof. Leszek Pacholski、Paweł Olszt等人发明。目前最新版本是1.0。

和 C#, VB.NET,F#等现有的.NET家族成员不同,Nemerle 是种多范式的编程语言,之所以称之为多范式语言,是因为它支持以下范式:

  • 面向对象编程 Object-Oriented Programming (OOP)
  • 函数式编程 Functional Programming (FP)
  • 元编程 Metaprogramming (MP)
  • 面向组件编程 Component-Oriented Programming (COP)
  • 面向领域专用语言编程DSL-Oriented Programming (DOP) 或面向语言编程Language Oriented Programming (LOP).
  • Nemerle 中最突出的是其元编程能力,它是基于和Lisp语言类似的宏的机制。

    设置Nemerle编译环境
    最新发布的Nemerle 1.0版本提供了和Visual studio 2010集成的能力,你可以在google code上下载到最新的版本。你需要的是基于.NET 4.0的Nemerle语言包Nemerle VS2010扩展这两个Zip文件。

    安装Nemerle很简单,用7-Zip打开VS 2010扩展文件的压缩包,双击包内后缀为vsix文件,就可以自动安装Visual studio 2010的Nemerle语言的支持。然后再将Nemerle语言包直接解压到”%Program files%\nemerle”目录即可,%program files%视你的操作系统略有不同,在32位Windows上,它指的是C:\Program Files,而在64位Windows系统上,则应该是C:\Program files (x86)目录。

    >>> 阅读全文

     

    , ,

    C# 4.0中的可选参数

    适用C#版本:4.0+。

    可选参数这个概念最早来自于Visual Basic,而后为Ruby等等动态语言所广泛采用。在C# 2.0年代,并没有可选参数这个概念。 这个限制是因为在 C# 中,任何地方都引入面向对象思想,所以尽量使用重载而不是可选参数。

    class MsgEcho
    {
      public MsgEcho():this("hi,world")
      {
      }
      public MsgEcho(String name)
      {
         Console.WriteLine(name);
      }
    }

    可选参数(Optional parameters)是C# 4.0的一个新特性,可以为一个方法的参数设置一个默认值。为一个参数设置一个默认值,这个参数就是可选参数,一旦被调用的方法忽略可选参数,就会用默认值代替。

    为什么需要开放命名参数和可选参数呢?这是出于动态语言运行时兼容性的要求。动态语言中存在动态绑定的参数列表,有时候并不是所有的参数值都需要指定(有些语言可能没有重载决策);另外,在一些 COM 互操作时,往往 COM Invoke 的方法参数列表非常的长(例如 ExcelApplication.Save,可能需要 12 个参数),但 COM 暴露的参数的实际值往往为 null,只有很少一部分参数需要指定植,如 ExcelApplication.Save(),可能不需要指定任何参数值,或者仅仅一个值,例如 fileType

    合 Visual Basic、Visual C++ 或者 Delphi 一样,C# 声明可选参数的方法就是在方法参数声明后面加上参数的默认值:

    >>> 阅读全文

     

    ,

    创建基于模板的WPF定制控件

    WPF可以创建两种控件,它们的名字也很容易让人混淆:用户控件(User Control)和定制控件(Customer Control),之所以如此命名,是因为用户控件更面向控件的“使用者”,以方面他们利用现成的控件组合成新的控件,而定制控件,更便于定制化(Customization),方便创建有别于现有控件的定制控件。

    定制控件提供了行为和表现完全分离的开发模式,具有很高的灵活性,当然,也更难一些。这里我们通过创建个简单的搜索控件来看看如何开发定制控件:

    首先我们创建一个WPF应用,在同一个solution里,再添加一个用户WPF控件库。
    系统会自动在控件库里创建一个UserControl1.XAML,这个文件可以直接删除。在WPF控件库里添加一个新的项目,注意:应该选择定制控件而不是用户控件,如图:

    >>> 阅读全文

     

    , ,

    手工打造JVM

    本文所介绍虚拟机被应用到一个真正的项目中:墨菲斯 – Silverlight 1.1的原型。在本文的附件中的演示讲解了虚拟机是如何工作,你也可以阅读附件中的源代码。不过注意,这儿的实现和任何既有的商业实现都不尽相同。为了节约时间,只要JVM规格书没有详细说明的,我们就采用最简单的方式加以实现。

    JVM的各个部分

    类文件结构
    这个JVM首先就需要个能将各个Java类组合起来的应用,所以谈任何类之前,首先就得定义一个结构“JavaClassFileFormat.”

    struct  JavaClassFileFormat
         {
             u4 magic;
             u2 minor_version;
             u2 major_version;
             u2 constant_pool_count;
             cp_info **constant_pool; //[constant_pool_count-1];
             u2 access_flags;
             u2 this_class;
             u2 super_class;
             u2 interfaces_count;
             u2* interfaces; //[interfaces_count];
             u2 fields_count;
             field_info_ex *fields; //[fields_count];
             u2 methods_count;
             method_info_ex* methods; //[methods_count];
             u2 attributes_count;
             attribute_info** attributes; //[attributes_count];
         };

    我们看到标有注释的地方,还定义了一些其他的结构,他们用来表示类文件的常量池(类文件中使用的常量)、字段、方法和属性,这儿我们先列出其定义,稍后再详细解释。

    struct cp_info
         {
             u1 tag;
             u1* info;
         };
     
         struct field_info
         {
             u2 access_flags;
             u2 name_index;
             u2 descriptor_index;
             u2 attributes_count;
             attribute_info* attributes; //[attributes_count];
         };
         
         struct method_info
         {
             u2 access_flags;
             u2 name_index;
             u2 descriptor_index;
             u2 attributes_count;
             attribute_info* attributes; //[attributes_count];
         };
         
         struct attribute_info
         {
             u2 attribute_name_index;
             u4 attribute_length;
             u1* info;//[attribute_length];
         };

    现在要做的是把类文件按字节读到内存中,再用JavaClass对象解析这些原始字节,逐一确定字段、方法、异常表等等。JavaClass类表示一个类在内存中的结构化形式。它有一个指针,指向所加载的类文件的原始字节流。

    >>> 阅读全文

     

    , ,

    Axum, 一切为了并行 (二)

    [b]代理编程[/b]

    上面的斐波那契数列的例子只是展示了一个微不足道的构建数据流网的例子。这类网络适合那些“数据流入,数据流出”的场景,但它不能指定数据如何在网络中传播,也不允许不同类型的数据流入或者流出网络。

    代理与通道给了我们创建复杂数据流网所需的一切。

    通过通道沟通的两个代理是种弱关系:它不需要知道或关系另一个代理是如何实现的。它们之间的“契约”只由通道指定。借用OOP中的概念,通道扮演了接口的角色,而代理则是实现了该接口的类。

    使用通道时,你向输入端口发送数据,从输出端口接受数据,这里,输入端口扮演了目标,而输出端口扮演了源头。而实现通道时,输入端口则是源头,输出端口则是目标。这有点难以理解,想想家里的水处理机,如果水是数据的话,考虑水的流向,你把水倒入入水口(水相对于你是流出),从出水口接水(水相对于你是流入),而处理机内部而言,水则是从进水口流入,从出水口流出。

    >>> 阅读全文

     

    , , , ,

    用C#编写 IE BHO

    在前面几篇文章都是用 VC++ 完成的,为了更加快开发速度,很多程序员会考虑使用 C# 等更便捷的开发方式,这里我们采用 Visual Studio 2010 作为开发工具,你也可以采用 Visual studio 2008,其界面和开发过程与 Visual Studio 2010 类似。

    这儿, 我们也简单介绍一下 BHO. BHO 是将自定义功能添加到 Internet Explorer 的轻型 DLL 扩展,除了 IE, BHO 还可以将功能添加到 Windows 资源管理器外壳程序. BHO 通常并不提供其自身的任何用户界面 (UI)。它们而是通过在后台响应浏览器事件和用户输入数据来发挥作用。例如,BHO 可以拦截弹出窗口、自动填充窗体或为鼠标手势添加支持。

    在阅读本文之前,建议安装 Visual studio 的 SDK,因为里面提供了包装了 OLE 的装配件, >> 点击下载。如果觉得 Visual Studio SDK 安装包太庞大, 本文也提供了需要几个 OLE 接口的C#源代码。

    我们知道,BHO 的生命周期与它所交互的浏览器实例的生命周期相等。在 IE 6 和早期版本中,这意味着要为每个新的顶层窗口创建(和销毁)一个新 BHO。在IE 7中则是为每个选项卡都创建和销毁一个新 BHO。

    BHO 必须实现 IObjectWithSite 接口, 该接口提供了两个方法GetSite和SetSite。请在项目中引用” Microsoft.VisualStudio.OLE.Interop “这个装配件。如果没有安装 Visual Studio SDK, 你可以在项目中加入这段 IObjectWithSite 接口的源代码。

    >>> 阅读全文

     

    , , , ,

    初窥Nemerle语言

    Nemerle是Microsoft的研究项目之一,由 Wrocław 大学的Kamil Skalski、Michał Moskal、Prof. Leszek Pacholski、Paweł Olszt等人发明,从2003年0.2版本开始,Nemerle不断地在改进中。

    作为一种新的语言,Nemerle有什么特点呢? Nemerle是一种多范型的语言(面向对象和函数式),完全支持编译器宏(更类似是Lisp的变种,而不是C++),以及许多其他的东西。Nemerla与VS2010里发布的F#不同,后者是纯函数式语言。因此,Nemerle提供了与C#近似的语法和强大的元编程系统。

    有关meta-program可以参考:wiki百科

    你可以在官方站点下载它的最新发布,在发布包中还带有与visual studio的集成的IDE,可以很方便地学习Nemerle语言,最新版本是1.0 RC1。

    这篇文章将带你快速浏览一下Nemerle的一些语言特性。

    >>> 阅读全文

     

    , , ,

    .NET编译器构造工具Irony

    简介
    Irony(不是 IronRuby),是个全新的 .NET 开源项目,其设计目的是为了提供一整套库和工具,以方便在 .NET 平台上实现自己的语言。目前它处于开发的第一阶段,即包括构造编译器的两个前端模块 — 扫描器和解析器。本文将对其技术稍作概述,并着重关注用 Irony 实现解析器。你可以在 CodePlex上找到该项目

    Irony 在编译器构造方面引入了许多规则创新。和广泛使用的解析器创建工具类似,Irony 也基于语法规范来产生出可工作的解析器。不同的是,Irony 并不采用独立的元语言来编码目标语法。反之, 在 Irony 中,语法元素被表示为 .NET 对象,并用 C# 使用类 BNF 的表达式对目标语法进行编码。另外,Irony 不会生成额外代码 — Irony 的 LALR 解析器使用源自 C# 语法的编码信息来控制解析过程。

    示例
    本文所附的下载包中包含了 Irony 的核心装配件、语法浏览器和一系列解析器样例:包括数学表达式的解析器、Schema、Python 和 Ruby 的语法简化版解析器。利用语法浏览器,你可以查看语法案例的分析数据,并利用代码例子来测试解析器。下图是语法浏览器解析语法树的场景:

    如果你想体验一下 Irony 项目,你只需要:

    • 1. 下载并解压源代码
    • 2. 用 Visual Studio 打开 Irony_all.sln 方案文件
    • 3. 将 GrammarExplorer 项目设为启动项目
    • 4. 按 F5 创建并运行应用
    • 5. 当语法浏览器的窗口出现的时候,在顶部的组合框内选择”grammer”,并浏览语法数据
    • 6. 从 Irony.Samples\SourceSamples 文件夹中加载源代码示例
    • 7. 解析源代码并浏览输出的语法树

    背景
    许多新潮的应用都用了这样或者那样的解析技术。比如编译器的开发就是严重依赖于解析器的一个现实例子。其他例子还包括了脚本引擎、表达式计算器(evaluator)、源代码分析和重构工具、基于模板的代码生成、格式化和彩色显示、数据导入和转换工具等等。因此,对于开发者来说,拥有快速直接的方法来实现所需的解析器就很重要了。不过不幸的是,就目前技术而言实现解析器仍然是个重大挑战。

    >>> 阅读全文

     

    , , , ,

    Ironruby与CLR语言的互操作性 (二)

    引用 .NET 的 Assembly
    除了我们前面提到的 require <PartialName> 和 require <Strongname> 外,Ironruby 1.0发布的时候,还提供了一个新的函数 load_assembly,这个函数的参数为 Assembly 的名称,在内部,load_assembly 会先调用 Assembly.Load,如果找不到这个 Assembly,那就再调用 Assembly.LoadWithPartialName。它也支持 require 的两种调用方法。除此之外,load_assembly 还可以接受第二个参数,指明只引用该 Assembly 下的某个名称空间,比如:

    load_assembly ‘IronRuby.Libraries’, ‘IronRuby.StandardLibrary.StringIO’

    名称空间
    当装配件被加载之后,它的顶层名称空间和类在 ironruby 内是可见的。比如下面这个例子

    namespace Models {  
      public class Person {  
        private string name;  
        public Person(string name) {  
          this.name = name;  
        }  
        public string Name {    
          get {  
            return name;  
          }  
        }  
      }

    上面C#代码的名称空间“Models”与普通的ruby模块一样可被存取:

    >>> require ‘models’  
    => true  
    >>> Models  
    => Models  
    >>> Models.class  
    => Module

    需要注意几点:

    • 1.不可用小写的名称空间:Ruby 常量要求使用大写开头的名字,所以名称空间必须遵循 Ironruby 的要求。
    • 2.不可用“空”的名称空间: 对 IronRuby 来说,名称空间不能为空。而且由于 CLR 的名称空间只在有可访问的子类时才存在,因此假如名称空间的所有子类都是私有的,IronRuby 将无法访问该名称空间。所以名称空间内至少要有一个公共的可访问类。

    因为名称空间被视为 Ironruby 的普通模块,所以它和其他 ruby 模块一样,可以被 mixin.

    >>> 阅读全文

     

    , , , , ,

    Previous Posts