返回   cpper编程论坛 > C/CPP/TMP/GP
注册账号 论坛帮助 会员列表 日历事件 搜索 今日新帖 标记版面已读

回复
 
LinkBack 主题工具 显示模式
  #1 (permalink)  
旧 2005-07-31
高级会员
 
注册日期: 2002-10-11
帖子: 143
达明一排 正向着好的方向发展
默认 MiniTS 通用类型系统——谈异构类型系统的整合

MiniTS 通用类型系统——谈异构类型系统的整合
本文由原作者邹月明在 www.mini-type.com 发表,
如需转发本文请注明作者与出处,
再次感谢您对我们工作的尊重。
  近年来,随着 Java 的逐渐成熟,以及 ASP 、 Python 、 PHP 等脚本语言的大量普及,使得 “ 动态语言 ” 四个字越来越深入人心,而在这背后起着举足轻重作用的关键技术之一就是他们所共有的优点:具有动态特性的 类型系统。 是否具有 动态类型系统 ,已经成为判断现代编程语言的一个重要标志,也是今后编程语言与所有应用系统发展的必然方向。而 .NET 的迅速崛起,更让人们感受到动态类型系统的魅力,它独创地提供了一个与语言无关的公共语言运行时( CLR ),使不同语言编写的程序在一个统一的环境下运行成为了可能。这个“公共语言运行时”就是本文将详细讨论的通用类型系统。

相关知识
  在深入讨论之前,让我们先了解几个相关的概念:

  首先,什么是 类型系统 呢?

  每一种编程语言都有数据类型,而类型系统是数据类型的运行时处理系统。在编程语言中,每一个数据项,无论是常量还是变量,都有数据类型,它可能是基本的语言内置类型,也可能是复杂的用户自定义结构。类型系统在程序运行时负责将这些数据类型从语言符号映射成运行时数据结构,并提供处理这些数据结构所需要的运行时操作。

  由此可见,类型系统是编程语言的灵魂,更与每个开发人员息息相关。我们平时接触的编程语言所使用的类型系统大至分为两种,一种是静态类型系统,另一种就是动态类型系统。

  静态类型系统,最重要的优势就是很高的执行效率和较小的内存需求。 C 语言就是静态类型系统的一个重要代表。它的数据类型是在编译期就已经固定并在运行时不可改变。为了效率,它甚至放弃了很多运行时检查(比如数组越界检查等),而将保证程序正确性的繁重工作交给了编译器和开发人员。

  动态类型系统与静态类型系统正相反,极高的执行效率已经不是它所考虑的首要问题,它的主要目的是为程序的健状性与灵活性提供内置的强大支持。它为语言中的每一种数据类型提供了独立的元数据,用于在运行时处理与数据类型相关的操作,这使得类型转换检查和数组越界检查等运行时操作可以直接由类型系统本身来完成,减少了开发人员的负担。

  那么,动态类型系统与静态类型系统在具体的编程语言中有哪些差别呢?我们来看下面的两句伪代码:

long val = 256;

byte val2 = (byte)val;

  很明显,第二句将 val 变量的值强制类型转换成 byte ,并将其赋值给变量 val2 的过程发生了溢出错误,因为 val 变量的值 256 已经超出了 byte 类型所能表示的数据范围( 0-255 )。我们把这样一段错误代码分别交给静态语言和动态语言去执行,会产生什么结果呢?

  C 语言对这段代码不会产生任何错误信息,但 val2 变量却将被赋值为 0 。为什么会出现这样的错误结果呢?当然, C 语言没有运行时检查,所以在运行时无从知晓赋值操作的安全性是很正常的;由于编译器是静态编译,更无法知道 val 变量在运行时会是什么值。换句话说,静态语言本身无法提供一种机制来检查和避免这种运行时错误情况的发生,只好任其发展。上述错误结果就这样被隐藏在程序的运行过程中,直到软件的其它某个功能不正常时才会被测试人员注意到。要想定位这种错误是非常困难的,开发人员不得不面对各种可能的运行时错误的挑战。呣,挑战,无处不在!

  动态语言的执行结果却很简单。由于动态类型系统的功劳,程序会在执行到那条错误的赋值语句时产生一个溢出错误,这个错误可以在运行时捕捉到(面向对象的语言对于这种情况大多会抛出一个异常),这给程序的健状性和稳定性带来了很大的益处,也更方便开发人员调试程序。如果美国宇航局早一些使用具有动态类型系统的语言来编写关键系统的控制程序,相信掉下来的航天飞机会比现在少许多 ...

  综上所述,动态类型系统由于使用了运行时检查的动态特性而使得开发人员可以用相同的代码量写出更加键壮的应用系统;而静态类型系统正是由于省略了运行时检查而与动态类型系统相比有着更高的速度优势。两者各有优缺点,分别适应各自的应用领域,很难武断地分清孰优孰劣。

  下面,我们再来认识一下 通用类型系统 。类型系统从适用领域角度,又分为 专有类型系统 与 通用类型系统两种 。

  专有类型系统一般存在于某个专有语言的编译器或解释器中,它是为某种语言的特性而专门设计的,离开了语言本身,该类型系统就失去了存在的价值。

  而通用类型系统与专有类型系统的设计思想正相反,它定义了一种通用的、语言无关的类型规范,使其理论上可以支持所有的编程语言。通用类型系统的作用有哪些呢?

• 它建立了一个支持跨语言集成、类型安全的执行框架。

• 它提供了一个支持多种编程语言对象模型的完整实现。

• 它以某种方式定义了所有需要支持该类型系统的语言所必须遵守的规则,以确保不同语言编写的程序能够交互。

  目前,通用类型系统中最著名的实现应该是 .NET 的 CLR( Common Language Runtime ) 了,它以经过扩充的 PE 文件格式做为语言规范,只要编译器生成的文件格式符合要求,就能保证其代码在 .NET 上运行。这样一个聪明的可扩展性吸引了一些厂商将自己的编程语言向 .NET 系统移植。

  然而,在喧哗的背后我们却忽略了一个重要的人,那就是很早就进军企业应用领域的霸主 ——Java 。相对于 .NET 通用类型系统提出的语言无关性与各大厂商趋之若鹜的势头, Java 显然有些尴尬,但它必竟还是占领着企业应用的绝对优势,对此事不闻不问。这可急坏了那些做系统集成的技术人员 ......

  咦?写到这儿怎么越来越像讲故事了?文章的标题改为《类型系统传奇》是否更好一些? J

  前面介绍过了一些背景知识,下面我们再来了解一下企业应用中的整合难题。我们会试着比较一些其它解决方案的优劣,最后向您展示一种使用通用类型系统的完美解决方案。

  .NET与Java的整合难题
  提到系统集成,就不能不说 .NET 与 Java 的竞争关系。虽然近年来 .NET 在企业开发领域的成长速度非常快,但毕竟在企业级市场中, Java 的 J2EE 正如日中天,越来越多的大型应用都使用了 J2EE 解决方案。有了十多年的市场根基, Java 在企业服务器端的地位已经是根深蒂固、难以动摇。还是忘记那些关于“ .NET 会取代 Java ”之类的谣言吧。根据专家的预测, Java 或者 .NET 架构其中任何一方一统天下的可能性都极小,在可预见的未来一段时间里,将会出现 Java 和 .NET 共同瓜分应用软件基础平台的局面。虽然它们不会“和平共处”,但肯定会“长期并存”,这给企业集成的开发人员带来的挑战便是如何在这种“百花争艳”的局面下合理地利用“多党合作制”解决不同系统之间的通讯与整合难题。如果您做过系统集成工作,相信会对跨架构集成的难度与复杂度有着刻骨铭心的记忆。

  “那么,”您可能会在心里嘀咕:“前面提到 .NET 的通用类型系统不能解决这个问题吗?” .NET 的通用类型系统的确优秀,但请不要忘记 .NET 与 Java 的竞争关系, Java 有没有可能在 .NET 平台上实现 Java 编译器呢?答案当然是否定的。 .NET 提出的通用类型系统模型并不适合系统整合的一个重要原因是,它试图让所有的语言放弃他们自己的类型系统,完全采用 .NET 的通用类型系统,才能保证其在 .NET 上运行。这虽然是一个良好的整合方案,但对于 Java 这种同样有着良好基础架构和相当用户群的技术,如果移植到 .NET 平台就等于它自己的消亡。我们必须承认 Java 和 .NET 都同样是非常优秀的平台基础架构,而且它们对分布式组件技术都提供了良好的支持: Java 提供了 RMI , .NET 提供了 .NET Remoting 。在各自的领域内,这两种解决方案都工作得很好。但是,如前所述,当面临着 Java 和 .NET 长期共存的局面时,如何在这两大平台之间进行互相通讯的问题就越发显得紧迫。因为无论是 RMI 还是 .NET Remoting ,都不能够连接到对方的平台。特别是大型的企业,不可避免地需要面对在异构平台之间进行集成的问题,因此企业对跨架构集成的优秀解决方案的需求也将越来越迫切。

  说到这儿,您一定会想到另外一种非常著名的技术,那就是 Web Service 。 Web Service 可用于访问远程机器上的对象,基于标准的 XML 做为数据封装格式。由于它的格式简单、开放,同时又不依赖于任何平台和编程语言,使其一度被看做系统集成的“银弹”,但是在实践中,人们很快就发现 Web Service 并不像预想中的那样完美。因为它存在着如下一些缺陷,而且有些缺陷几乎是很难甚至无法彻底克服的:

• Web Service 技术本身虽然相对简单,但是为了通过 Web Service 进行通讯,服务器端和客户端程序都必须进行额外的架构,将原有的对象进行封装和暴露。这将需要投入额外的资源来进行编程和维护,更重要的是,涉及到对服务端的改动。而在一些关键性的应用中,由于对可靠性的要求极高,因此对于已经经过实际验证能够稳定运行的系统,进行改动带来的风险是很大的。

• Web Service 技术使用 Http 做为通讯协议,对于某些只需要在内部进行接口通讯、甚至只需要在本机进行跨架构通讯的简单需求,却不得不额外部署一台 Web 服务器(如果要实现互调用则需要至少两台),不但增加了系统的实施成本,而且严重影响到系统的性能。即使可以不采用 Http 协议做为 Web Service 的通讯载体,目前也没有出现任何一个成熟的、支持 Web Service 的、以非 Http 方式通讯的中间件产品。

• Web Service 使用了标准的 XML 作为数据封包的格式,虽然获得了良好的兼容性,但是也导致了在性能上的巨大损失。 XML 的字符流和传统的二进制流,数据包的大小已经可以让处理速度相差一个数量级以上,再加上 XML 的编码 / 解码与解析开销,性能差距会非常巨大。我们在网上的论坛不时会看到一些系统因为大量使用 Web Service 而频繁出现请求超时情况如何处理的问题。因此这也是在一些对性能要求苛刻的实时系统中, Web Service 基本不在考虑范围之内的主要原因。

  除了 Web Service ,还有一种解决方案是所谓“ Bridge ”模式的一种实现。这种技术使用专门的桥接器软件作为服务端和客户端的中转站。当客户端向服务端发送请求时,桥接器将截获请求并转换为服务端能够理解的格式,再转发给服务端。当服务器端发送回应时,同样也通过桥接器中转。很显然,这种桥接器解决方案由于对每次调用都要进行多达至少两次的转发而存在着严重的性能问题。

最终解决方案
  那么,有没有这样一种完美解决方案,既能提供高效的远程跨架构的通讯,又能对本地跨架构通讯做充分的优化(这种情况不应该以远程通讯协议的方式调用而应该直接做本地调用) 呢?还有最重要的一点:这种解决方案应该对原有系统的冲击最小,不会导致对现有系统代码的大幅修改。在最好的情况下,该解决方案能够在背后起作用,应用系统里基本不会出现与该解决方案相关的代码……呣,看起来真的很难哦!

  这种要求真的能实现吗?当然可以,否则您就不会在这里看到这篇文章了。那么这个解决方案是什么?答案是: 通用类型系统 。

  咦!转了一圈怎么又回到了通用类型系统?这里所说的通用类型系统当然与 .NET 的通用类型系统有些不同。 .NET 的通用类型系统是将一种可执行文件格式做为系统规范,这无形中增高了对语言支持的门槛,试想一下,这世界上真正能为 .NET 写编译器的人又有多少呢?再有, .NET 强迫其它语言使用 CLR 类型系统,这使得一些语言因为不愿放弃自己的核心架构而取消向 .NET 移植的计划。

  那么,我们是不是可以换一种思路:如果有这样一个高效的通用类型系统,它在软件互调用的通信协议层制定一个二进制的规范做为不同语言编程接口的基础,那么对各种语言来说实现互操作的难度就有了相当大程度的降低。同时,该类型系统以兼容的方式支持所有语言,而并不要求所有语言都采用自己的类型系统。这种设计不但无需改变现有系统的代码,而且让不同语言依旧能够发挥它们自己的独特优势,在整个系统中发挥其不可替代的作用。

  最近刚刚面世并提供下载的免费软件 MiniTS ( http://www.mini-type.com )通用类型系统就在这方面做了大胆的尝试并成功推出了 1.0.6 版。您不想了解它的技术细节吗?

MiniTS 特色

  MiniTS 是一个旨在将 C/C++ 、 .NET 、 Java 等各种系统无缝集成,并保持系统之间耦合度较低的一个通用类型系统实现。使用它,可以在某一种语言中可以取得在其它任何语言实时动态定义的类型及数据、以动态调用其它任何语言的模块,而无需关心这些程序散布在网络的任何角落。

  MiniTS 不是为了改变现有程序的开发方式而设计的。相反,在保持当前程序开发方式不变的同时,它试图将跨系统集成的难度与复杂度降至最低。甚至使用者感觉不到 MiniTS 的存在,所有的跨架构、跨语言调用实际上只是在与当前语言的另外一个模块做本地调用,这大大地降低了大型项目的实施风险与开发难度。

  对于已经具有动态类型系统的架构,如: .NET 、 Java 等, MiniTS 会直接使用该架构的内置类型系统与其它系统进行通讯。这时,调用方根本感觉不到 MiniTS 的存在,但 MiniTS 会在后台默默地提供着类型支持。当调用方请求一个类型、传递一段数据、调用一个方法,而它是在其它架构的语言中定义的时候, MiniTS 会自动地从网络或本机中取得相关的数据,并返回给调用方;而如果调用方请求的资源已经存在,则 MiniTS 不做任何事情。

  对于静态类型系统的架构,如: C/C++ , MiniTS 提供了一整套完整、高效的,能与与其它架构无缝整合的通用类型系统,使该系统具备动态语言的特性。

  MiniTS 依靠内置的跨架构通讯核心,实现了一个独特的与语言无关的可编程的扩展架构,详细内容将在“ MiniTS 调用绑定模式”部分介绍。

  与前面所述的其它解决方案相比, MiniTS 采用了一个独特的技术角度切入,用 C/C++ 从系统底层直接实现了一个与 .NET 和 Java 兼容的通用类型系统,它以标准 C 库的方式提供。为什么类型系统核心使用 C / C++ 来实现呢:原因有如下几点:

• 严谨的 C/C++ 实现方式保证了类型系统本身从设计上将效率放在第一位的理念。与其它一些基于 .NET 或者基于 Java 的实现方式相比,这种内核实现方式更有效率。

• 考虑到解决跨架构功能调用的效率与可能性。绝大多数基础平台架构都是用 C 语言开发的, C 接口很自然的成为效率最高、最直接的调用途径。与其它一些基于 .NET 或者基于 Java 的实现方式相比,这种调用方式比 PInvoke 类似的调用更有效率,而且具有良好的扩展性,便于支持其它架构。

• 我一直梦想着拥有一个以标准 ANSI C 库的方式提供的、没有由于依赖虚拟机而产生额外资源浪费的、跨平台的通用类型系统,最后,我终于自己实现了 MiniTS 。我相信它会被更多真正的 C/C++ 开发人员喜欢。“咦? .NET 不是有一个 C++/CLI 可用吗?”不错,但那已经是一门与 C/C++ 没有什么关系的新语言,对标准 C++ 语法的多余支持倒不如说是一种兼容。还有最重要的一点:目前世界上只有微软的一款编译器能够编译 C++/CLI 代码……

MiniTS 对象模型

  MiniTS 提供了一个动态的单根继承对象模型,不但与目前流行的语言如 C# 、 Java 完全兼容,而且拥有 C# 与 Java 都不具备的动态特性,比如 MiniTS 可以在运行时增加或修改一个类的定义,还可以在运行时修改一个接口的方法定义或者为一个接口增删方法,甚至直接创建一个接口类。首先,最基本的,它提供了一组跨平台的内置数据类型:

• 整数类型: SByte 、 Byte 、 Int16 、 UInt16 、 Int32 、 UInt32 、 Int64 、 UInt64

• 浮点类型: Single ( 32 位)、 Double ( 64 位)

• 日期时间: DateTime 、 Date 、 Time 、 TimeSpan

• 二 进 制: Binary

• 全局标识: Guid

• 接口类型: Interface

• 容器类型: Array 、 List 、 Deque 、 Hashtable 、 Map

• 其它类型: String 、 Char 、 Boolean 、 Void

  除了上述类型, MiniTS 还以 Class 做为基类,支持完全动态的用户自定义类型,该类型支持继承、嵌套、支持 DownCast ,其能够达到的复杂程度与高级语言对类的支持相同。

  对于绝大多数系统来说,字符串类型数据在调用过程中所占比率相当高。而对于字符串, MiniTS 也有着独特的处理方式。大多数中间件系统(包括 .NET 、 Java 在内),字符串在传递过程中都将其转成了 UTF8 码,对于英文语系的国家,这种转换的时间和空间开销都非常低,但对于使用多字节语言的国家(如中国),这种转换的开销是不容忽视的。根据 UTF8 的编码规定,一个占用两个字节的中国汉字在 UTF8 编码中可能会占用多达三个字节, 严重浪费了资源也影响了效率。为了解决这个问题, MiniTS 在传输过程中优先对字符串内容使用 GB2312 编码(也就是说对在中国,字符串传递不需要编码),这可以极大地提高字符串数据传输的效率。为了控制编码方式,在通讯协议中包括当前数据包中字符串编码方式,由接收方根据需要对字符串数据做编码转换工作。这是一个细节,而正是这些细节,体现了使用本土软件的优势! J 所以请支持国产软件!

MiniTS 传输协议

  MiniTS 有一个 MiniRemoting 模块专门为各种协议提供可扩展的、统一的访问接口并对协议细节做完整的封装。目前 MiniTS 的内部通讯协议采用自定义的二进制格式。 MiniTS 的默认通讯协议层为所有面向对象语言提供了完整数据类型的支持。除此之外,又为某些专有系统的特色类型功能做了特殊支持。如 C# 语言的 struct 的实例是在托管栈上分配的而 class 的实例是在托管堆上分配的,这种代表语言特色的功能在数据传递的过程中会保留原先的语意。

  另外, 在异构系统之间通讯的细节已经在与语言相关的编程接口中被封装,调用方根本不用关心协议的任何细节,哪怕今后对默认通讯协议的更新也不会导致编程接口的变化。以此做基础, MiniTS 在今后将支持更多的知名协议格式以扩大其兼容性优势。

  对于网络传输协议,目前考虑到对稳定性的要求,只采用了 tcp 做为系统的默认通讯协议,今后会支持 UDP 并将采用标准的 SSL 提供安全的通讯。

MiniTS 调用绑定模式

  依靠内置的跨架构通讯核心, MiniTS 实现了一个独特的、与语言无关的可扩展的调用架构。 对于异构方法调用, MiniTS 既提供了早绑定调用模式,也提供了晚绑定调用模式。

  对于早绑定,主要用于为 MiniTS 写的扩展模块、以及今后在 MiniTS 应用服务器上写的扩展服务模块中使用的,为了解决某些已经固定的调用需求而设计的。对于晚绑定,主要用于解决非常灵活的动态调用需求。

  与众不同的是: MiniTS 对于扩展模块竟然没有过多的约束,您可以随意编写自己的模块并编译,只需要在将其加入 MiniTS 系统时提供一份接口声明即可。当然如果您愿意,这份接口声明可以编译在您的模块中,这样 MiniTS 就可以自动装载该模块并在需要时调用它,并可以提供类型安全的调用服务。在为 MiniTS 所编写的模块中,根本无须考虑其它细节,所有的网络通讯等其它事情都由 MiniTS 自动完成,而您的模块中写的完全是真正的:程序。 J

  与 COM 、 CORBA 及其它类似产品不同, MiniTS 并不包含 IDL 之类的中间接口定义语言,也根本不需要它。为什么呢?因为 MiniTS 是一个完全动态的类型系统,所有的对象类型细节都可以使用编程接口完成,使用了 IDL 或其替代物,势必需要做源代码生成,这又使其“退化”到了静态的情况,因为您必须要对生成的源代码做编译。由动态系统生成与系统分离的、难以扩展与维护的、静态的模块,这不可笑吗?

  MiniTS 内置名字服务( Naming Service )机制,这使得调用某个接口的方法时无需知道该接口在网络的哪个角落里,因为 MiniTS 会使用其名字服务找到该对象并在本地做高速缓存。

功能展望
  目前, MiniTS 已经支持 HTTP 协议,并已经基本完成了一个相当高效的支持服务器端处理程序的 Web 服务器。设计该功能的目的并不是为了让 MiniTS 简单的提供 Web 服务器的功能,而是准备在内核直接支持 Web Service ,而让已经布署到系统的、以任意语言编写的模块可以自动对外提供 Web Service 和 MiniTS 协议的调用服务。

  内容检索已经越发成为人们重视的焦点, MiniTS 已经开始着手构建自主产权的全文内容检索功能。并将于近期推出集成该功能的版本。

尾声
  随着企业信息化的逐步深入,异构系统整合的紧迫性将越来越明显。 MiniTS 从通用类型系统的角度试图解决这个问题,做了一些大胆的尝试并取得了阶断性的成果。如果您感兴趣,欢迎随时与我联系,深讨与本文有关的技术问题。







电子邮箱:用户名是 da_ming 服务器是 hotmail.com
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #2 (permalink)  
旧 2005-07-31
Elminster 的头像
超级版主
 
注册日期: 2002-09-09
帖子: 1,764
Elminster 正向着好的方向发展
默认

这算是广告么?

引用:
  由此可见,类型系统是编程语言的灵魂,更与每个开发人员息息相关。我们平时接触的编程语言所使用的类型系统大至分为两种,一种是静态类型系统,另一种就是动态类型系统。

  静态类型系统,最重要的优势就是很高的执行效率和较小的内存需求。 C 语言就是静态类型系统的一个重要代表。它的数据类型是在编译期就已经固定并在运行时不可改变。为了效率,它甚至放弃了很多运行时检查(比如数组越界检查等),而将保证程序正确性的繁重工作交给了编译器和开发人员。

  动态类型系统与静态类型系统正相反,极高的执行效率已经不是它所考虑的首要问题,它的主要目的是为程序的健状性与灵活性提供内置的强大支持。它为语言中的每一种数据类型提供了独立的元数据,用于在运行时处理与数据类型相关的操作,这使得类型转换检查和数组越界检查等运行时操作可以直接由类型系统本身来完成,减少了开发人员的负担。
这一段就是常识性错误了。所谓动态类型系统和静态类型系统,它们之间主要的差别根本不是运行时检查,也不在于是否提供元数据。区分静态动态类型系统,最基本的一点是变量的类型是否能够在运行时改变 ── 这一点楼主倒也提到了 ── 但更本质性的区别在于是否能够在运行时“载入”一个新的类型,是否能够在运行时改变一个类型,比如为某个类添加一些成员等等。人们一般认为,这两条才是动态类型系统最有价值的地方。

这里尤其要指出的是,在健壮性和错误检查这个问题上,目前一致公认是静态类型系统的语言占有很大优势。这是因为静态类型系统可以提供编译时检查,比方说,如果你试图在某个对象身上调用一个不存在的成员方法,编译器立刻就会发现并报错 ── 这里根据检查的严格彻底与否,还有强类型和弱类型的说法。而动态类型系统,必须要等到运行时才能发现这一类的错误,相比之下,发现错误的能力弱了不止一个数量级。

至于这个东西么,目前能看到的全是广告词,没什么实质性内容。楼主给段使用的例子?
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #3 (permalink)  
旧 2005-08-01
高级会员
 
注册日期: 2004-12-06
帖子: 142
哑巴英语 正向着好的方向发展
默认

能不能给个确实的定位。这样子的大旗兜得住么?


mini C 接口

它是 MiniSvc 的底层功能实现,有了它,就有了 MiniTS 的全世界。

因为 MiniTS 大部分功能用 C++ 实现,所以目前并不是所有功能都
可以直接由纯 C 程序调用,但所有功能肯定可以由纯 C++ 程序调用。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #4 (permalink)  
旧 2005-08-04
高级会员
 
注册日期: 2002-10-11
帖子: 143
达明一排 正向着好的方向发展
默认 sorry, 这样的贴子难TAO广告之嫌,但我主要还是想和大家聊一聊

虽然大部分功能用C++实现,但对外提供的肯定是纯C的,动态装载接口。
附件的 mini_c.h 就是C接口。大家帮看看这种接口是否合适呢。
上传的附件
文件类型: c invokec.c (3.5 KB, 7 次查看)
文件类型: c helloworld.c (1.9 KB, 7 次查看)
文件类型: h mini_c.h (118.8 KB, 7 次查看)
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #5 (permalink)  
旧 2005-08-04
高级会员
 
注册日期: 2002-10-11
帖子: 143
达明一排 正向着好的方向发展
默认 这是几个在.NET上的调用举例子

因为.NET内置动态类型系统了,所以Mini会与它完全溶合在一起:

呜呜,为什么我传不上附件 了?在一个thread里不能超过一个贴子有附件?
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #6 (permalink)  
旧 2005-08-06
cppof286 的头像
高级会员
 
注册日期: 2004-11-24
住址: 已经在北京了
帖子: 147
cppof286 正向着好的方向发展
发送 MSN 消息给 cppof286
默认

引用:
作者: 达明一排
与众不同的是: MiniTS 对于扩展模块竟然没有过多的约束,您可以随意编写自己的模块并编译,只需要在将其加入 MiniTS 系统时提供一份接口声明即可。当然如果您愿意,这份接口声明可以编译在您的模块中,这样 MiniTS 就可以自动装载该模块并在需要时调用它,并可以提供类型安全的调用服务。在为 MiniTS 所编写的模块中,根本无须考虑其它细节,所有的网络通讯等其它事情都由 MiniTS 自动完成,而您的模块中写的完全是真正的:程序。
听起来非常接近陈榕经常强调的“元数据”啊,接口以元数据的方式保存在模块当中,然后通过运行时系统自动识别和转载。

不过前辈啊,这句话似乎和你前面所说的相反呢:
引用:
作者: 达明一排
与 COM 、 CORBA 及其它类似产品不同, MiniTS 并不包含 IDL 之类的中间接口定义语言,也根本不需要它。
即便你的MiniTS是一个动态可装载的类型系统,你的接口原型也仍然需要说明啊:
你的接口的参数、参数的类型,哪一个不需要程序员讲明白?

以前我因为工作原因开始学Ocaml,所以有机会了解了一些Ocaml运行时环境对C接口的处理方式。前辈说MiniTS采用的是动态类型框架,那么它的设计思路应该和Ocaml很接近才对,即所有的接口的形式参数都被置换成一个统一的value,然后代码里面通过中间框架提供的类型转换函数处理转换。换句话说,如果我使用C语言开发MiniTS系统的模块,则我的代码中必然需要手工处理大量的转型操作。老实说,我用OCaml的时间很短,但是用Python比较多。Python的运行时环境也是采用了类似的方法处理接口的。根据个人这几年来的经验,说实话,这种写代码的方式恐怕相当烦琐,还是ICE那种接口定义语言的方法感觉好一点。

引用:
作者: 达明一排
对于绝大多数系统来说,字符串类型数据在调用过程中所占比率相当高。而对于字符串, MiniTS 也有着独特的处理方式。大多数中间件系统(包括 .NET 、 Java 在内),字符串在传递过程中都将其转成了 UTF8 码,对于英文语系的国家,这种转换的时间和空间开销都非常低,但对于使用多字节语言的国家(如中国),这种转换的开销是不容忽视的。根据 UTF8 的编码规定,一个占用两个字节的中国汉字在 UTF8 编码中可能会占用多达三个字节, 严重浪费了资源也影响了效率。为了解决这个问题, MiniTS 在传输过程中优先对字符串内容使用 GB2312 编码(也就是说对在中国,字符串传递不需要编码),这可以极大地提高字符串数据传输的效率。为了控制编码方式,在通讯协议中包括当前数据包中字符串编码方式,由接收方根据需要对字符串数据做编码转换工作。这是一个细节,而正是这些细节,体现了使用本土软件的优势! 所以请支持国产软件!
这一点不敢苟同。我承认UTF-8在表示中文字符时比较浪费空间(大部分是三个字节,少数扩展字符甚至达到了四个甚至是六个字节),但是UTF-8编码用这种浪费换来的是强大的检错能力:在网络传输错误时,UTF-8可以将错误定位到具体的某一个字符的某个字节。相反的,现在东亚各国的通行编码(包括我们中国的GB系列、Big5系列,也包括日本韩国的编码),都没有这个能力,因为他们的同一两字节或者四字节编码没有前缀码作为保证,一旦一个字节添加或者缺失某些位则其后续几乎所有的字符都无法正确解码。另外,GB2312本身到UNICODE的字符映射不全,而UTF-8则可以实现UNICODE编码的一个完整映射。所以如果是我负责设计,我绝对优先使用UTF-8编码。


前辈的这个构想让我想起了ICE,如果真的做成了的话,相信会是一个很有意思的东西
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #7 (permalink)  
旧 2005-08-06
高级会员
 
注册日期: 2002-10-11
帖子: 143
达明一排 正向着好的方向发展
默认 非常高兴能与大家交流

  千万别说前辈之类的话,论资历与水平,我与坛子里的高手根本没法比,只不过是我把自己的想法公开出来了而已。

  对于你提到的我的文章中前面说“不需要接口定义语言”后面却说“需要一份接口说明”,这的确是文章前后矛盾的地方,我承认。实际上,无论以何种方式实现的动态类型系统,都肯定需要元数据,元数据又如何输入到系统中?这就肯定需要接口说明。只不过 MiniTS 的实现中将接口声明直接拿去创建了类型对象而不是像Corba、COM那样去生成代码,这是它们之间最大的区别,也是MiniTS比它们都灵活的重要原因。试想一下,用Corba、COM、ICE或者其它的东西需要用IDL语言定义接口,最要命的是它们都把接口编译成了源码,当程序编译好了以后要增删改接口怎么办?布署人员是没有办法了,必须要开发人员修改IDL文件,再编译成源码,然后再实现了这些接口,再给布署人员,布署人员的工作就是拷贝文件。这是个多么浩大的工程?

  对于你说到的用 C 给 MiniTS 写模块可能会由于把相当大的精力都放在了数据类型的转换上而相当复杂。我非常高兴讨论这个问题,因为我也是 C/C++ 开发人员,所以我在 MiniTS 设计的初期就把这种情况放在相当重要的位置上来考虑。接下来,我们实际写一个 MiniTS 的模块来看看为它写一个模块到底有多复杂:

/*
* 所有使用 MiniTS C 接口的程序必须包含此头文件
*/
#include <mini/mini_c.h>

/*
* 模块实现声明。
* 该语句应该放在头文件中。
*/
MINI_DEFINE_MODULE()

以上是一些公式性的代码,可以不去看它。


接下来我们要实现一个静态函数,做一个加法,你认为它有多复杂呢?你认为怎么样才算不复杂呢?我相信下面的实现会让绝大多数对 MiniTS 持怀疑态度的人意外:

/*
* 一个自定义函数。该函数稍后将做为一个接口对象的方法发布。
*/
int add( int a, int b )
{
return a + b;
}

  对于实现函数来说,它根本不知道什么叫MiniTS,根本不知道自己的函数会放在哪里被调用,因为它的确是一个普通得不能再普通的——函数。

  模块功能的实现可以是完全通用的代码,这是 MiniTS 设计的一大特色。大家可以去看看 CORBA, COM, ICE.... 等等目前已经出现的中间件系统,到处充满着与中间件系统名字相关的类型前缀,多烦呀?本来是通用代码,为什么要和某个中间件系统绑死?!


  再下面的工作就是如何把这个函数提交给 MiniTS 系统了。按照我最终的想法,这是在布署阶段做的工作。“什嘛?!类还没有呢,就一下跑到布署那里去了?!”你会这么想吗?呵呵,我和你一说你就理解了。根据上面的函数实现方式可以看出,提供功能实现的程序员对代码没有任何限制,他可以随心所欲的提供一个或多个通用函数库。现在假如客户需要一个 Math 类,要求下面有一个 Add 静态函数,那么布署人员就为其生成一份接口声明,并提交给系统,系统为其生成 Math 对象和 Add 方法,客户直接调用就OK了。写函数库的程序根本不知道自己的函数库是被如何调用的,而客户端也不知道他调的函数是本地调用还是远程调用、是用什么语言实现的,完全透明。

  按最初设计,最终 MiniTS 会提供一种纯编程接口的类型定义方式,还会提供一种与IDL兼容语法的类型定义方式,更会提供一种 XML 格式的类型定义方式。这给布署人员带来的极大的方便。但目前,MiniTS 只提供了纯编程接口的类型定义方式,为了简化代码,该类型定义方式被封装成了宏,下面是上述的 Math 类的定义代码:

/*
* 开始类型定义,在这里边可以定义多个接口类
*/
MINI_BEGIN_TYPES()

/*
* 定义一个接口对象,名称为 Math
*/
MINI_DEFINE_INTERFACE( "Math" )

/*
* 在接口对象下创建一个静态方法,名称为 'Add',实现函数是 add
*/
MINI_DEFINE_METHOD2( "static cdecl int Add( int a, int b );", add )

MINI_END_INTERFACE()

MINI_END_FUNC()


  以上就是客户要求的接口,按这种方式,程序写的功能实现代码可以实现相当高的代码重用。您可能会想到,你这定义语法是什么格式呀?这么像C++?sorry ,目前还没考虑标准化捏,在实现阶段嘛,实现了以后我肯定会支持IDL和XML的。“但是,”你可能会问:“如果我的成员函数过于复杂,以至于用一条语句无法描述怎么办?”这好办呀,我们可以用另外一种方法:

/*
* 开始类型定义,在这里边可以定义多个接口类
*/
MINI_BEGIN_TYPES()

/*
* 用另一种方式创建一个方法 Add,实现函数还是 add
* 这种方式虽然比用 MINI_DEFINE_METHOD2 复杂一些,但提供最大限度的
* 灵活性。所以,它绝不是为了定义如此简单的方法而设计的。
*/
MINI_DEFINE_METHOD(
MINI_STATIC, // 静态方法
"Add", // 方法名称
2, // 方法参数数量
MINI_CDECL, // 方法实现调用约定为 cdecl
add ) // 实现函数指针

// 返回类型
MINI_DEFINE_VAL_RET( int32 )

// 第一个参数
MINI_DEFINE_VAL_PARAM( MINI_IN, int32 )

// 第二个参数
MINI_DEFINE_VAL_PARAM( MINI_IN, int32 )

MINI_END_METHOD()

MINI_END_FUNC()

这回足够你做最细化的控制了吧?

最后,让我们完成这个模块的开发吧,写一个模块定义语句:

/*
* 定义模块,名称为 SimpleModule。
*/
MINI_IMPLEMENT_MODULE( "SimpleModule", 0 )


以上就是开发一个完整的 MiniTS 模块的步骤。

大家看这么做是否还有什么不方便或者设计不好的地方呢?

另外,现在已经支持了用C++实现的类,回头我写个例子。。。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #8 (permalink)  
旧 2005-08-06
高级会员
 
注册日期: 2002-10-11
帖子: 143
达明一排 正向着好的方向发展
默认 还有你对编码方式的讨论让我受益良多

我最初只是考虑到效率,并没有过多的考虑这种容错。对于我做的大多数应用。
数据传输的稳定性由TCP协议去保证,如果数据发生了错误,即使因为使用UTF8编码而使数据只错了一个字节,整个数据也是不可用的(虽然给人看是可以的)。

但是,MiniTS系统只是优先采用GB2312编码,只需要一个参数,就可以使用UTF8编码方式,所以你说的情况MiniTS是完全支持的。呵呵

所以,使用哪种编码方式,是调用方的事,MiniTS 这两种方式都支持。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #9 (permalink)  
旧 2005-08-06
高级会员
 
注册日期: 2002-10-11
帖子: 143
达明一排 正向着好的方向发展
默认

再转一篇关于 MiniTS 调用部分设计相关的文章:

Interface 是 MiniTS 主要的本地与远程通讯的动态调用接口, 今后的应用服务器将以它做为调用基础.

Interface 支持静态函数与成员函数,静态函数不需要类的实例就可以运行,也就是说InterfaceType 对象就可以直接调用静态函数, 而成员函数必须要类的实例才能调用, 它的第一个参数就是指向类的指针, 这个指针就是面向对象语言中的 this.

Interface 不但要支持 C 语言,更要无缝的支持 C++ 语言,同时为所有其它语言、架构与平台提供支持。

Interface 实例的创建与销毁过程:

Interface 对象的第一个函数指针用于指定 Interface 实例的字节数:
size_t InstanceSize();
MiniTS 引挚将调用此函数确定需要多少字节才能创建该接口对象的实例,并自动分配。

Interface 对象的第二个函数指针是 Interface 的 Placement Constructor:
void PlacementConstructor( void * raw_memory );
MiniTS 引挚将调用此函数来在已经分配好的内存上创建接口对象的实例。

Interface 对象的第三个函数指针是 Interface 的 Placement Destructor。
void PlacementDestructor( Interface * o );
MiniTS 引挚将调用此函数来在析构接口对象的实例。

最后,MiniTS 引挚会自动释放删除为接口对象分配的内存。



以上就是对象的规则,接口的实现程序必须实现以上函数,至少要实现前两个函数,当然特别是 Placement Constructor,如果该函数为空指针,则认为当前接口是一个纯虚接口而不允许直接创建它的实例。(巧妙地实现了abstract !)

涉及到 Interface 的细节以后,您一定会发现,MiniTS 好像是实现了 COM/DCOM应该实现的东西。对,是这样的。它实现了类似 COM/DCOM 的功能,但却远远比它有更好的易用性。为什么?因为 MiniTS 诞生的原因之一就是 COM 接口过于复杂的调用方接口以及平台相关性。

综上所述,COM 最著名的三个接口函数被 MiniTS 完全废弃,因为那是让接口过于复杂的原因之一:

1、QueryInterface:MiniTS 不需要在接口内查询,因为所有的接口都可以和类型一样以一种统一的方式查询,而 QueryInterface 却只能在某个特定的模块中查询接口。

2、AddRef 和 Release。这两个函数是使 COM 过于复杂、代码过于难看的重要源头!使用这两个接口,接口实现者必须自己担负复杂的内存管理、对象生存期管理,更重要的是让调用方也必须遵循过于严格的内存管理调用约定。有谁能在10分钟之内掌握这两个函数的用法并真正写出一个没有 Memory Leak 的 COM 客户端程序?这非常非常困难。

MiniTS 的解决方案是:由 MiniTS 系统承担内存管理与对象的生存期管理,接口实现者只需知道自己的接口是如何实现的即可。至于是使用引用计数方式还是使用Singleton 方式创建接口对象实例,那只需要做简单的配置,而与接口的实现完全无关。

按我的想法,接口的调用方程序大至是这样的,以下例子假设某个 MyInterface 定义了一个接口,它有一个如下方法
int32 MessageBox(
int32 hWnd,
const char * msg,
const char * title,
uint32 flags );
以下代码演示了如何调用此方法:

// 查询一个接口类型对象,该函数是标准的类型查询接口
// 调用方根本无需关心该接口类型是在本机定义的还是在网络的其它机器上定义
// 的,也不需要知道该接口是用什么语言实现的。
MiniType * interfaceType = mini_domain_get_type( "MyInterface" );

// 通过接口类型创建接口的实例,该函数是标准的创建对象实例接口
MiniObject * inst = mini_type_create_instance( interfaceType );


// 取得要调用的方法
MiniMethodInfo * method = mini_interface_get_method( inst, "MessageBox" );

// Begin Call

// msg 参数
MiniObject * msg = mini_create_string_copy( "HelloWorld" );
// flags 参数
MiniObject * flags = mini_create_uint32( MB_OK );

// 调用指定的方法
MiniObject * res = mini_method_invoke_4( method,
NULL, // 第一个参数为 0,只传入 NULL 即可,因为 int32 对象默认值是0
msg,
NULL, // 第二个参数为空串,只传入 NULL,因为 string 默认值是空串。
flags );

// 在这里使用函数的参数及返回值
// ...

// 删除参数及返回值对象
mini_delete_object( res );
mini_delete_object( msg );
mini_delete_object( flags );

// End Call

以上是一个完整的、没有 Memory Leak 的例子,在实际应用中,前三条语句一般都
会放在功能初始化函数中,所以只有 BeginCall 和 EndCall 之间的几句话有用。

而对于 C++ 客户端来说,MiniTS 已经提供了智能指针,调用代码更可以改成:

mini::ObjectPtr msg = mini_create_string_copy( "HelloWorld" );
mini::ObjectPtr flags = mini_create_uint32( MB_OK );

mini::ObjectPtr res = mini_method_invoke_4( inst, method,
NULL,
msg,
NULL,
flags );

这样,调用方完全不用关心对象的删除。
同时,这种机制也为调用方程序提供了足够的自由度,您可以使用 MiniTS 内置的
智能指针,可以使用 boost:hared_ptr,可以使用....

当然,这篇文章是以前写的,现在的C调用接口已经与文中写的完全不同了,但思路基本没有变化。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #10 (permalink)  
旧 2005-08-08
cppof286 的头像
高级会员
 
注册日期: 2004-11-24
住址: 已经在北京了
帖子: 147
cppof286 正向着好的方向发展
发送 MSN 消息给 cppof286
默认

没想到这么快就能得到达明兄的回答,真是高兴啊,哈哈哈

达明兄所描述的模块定义方法让我想起了Boost Python库和LVM库啊,像LVM库的C绑定就是用类似的方法实现接口定义的。所以这个方法我倒是能够理解,事实上也非常好用。

老兄所说的Cobra/COM的代码生成的缺点我也是赞同的。代码生成不适合经常变化的接口设计,在部署上也有问题。如果能够把元数据整合在目标代码内部,则这些问题就都不复存在。这倒是与Python的库组织方法很类似啊。不过话又说回来,即使是做了简化,在某些情况下少量的代码转换还是不可避免的:
引用:
作者: 达明一排
MiniObject * flags = mini_create_uint32( MB_OK );
实际上我说的 Python-C 接口中的类型转换也就是这个意思。只不过 Python 中需要转换的是 PyObject*,这里则是MiniObject*,原理上倒是一样的。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #11 (permalink)  
旧 2005-08-08
cppof286 的头像
高级会员
 
注册日期: 2004-11-24
住址: 已经在北京了
帖子: 147
cppof286 正向着好的方向发展
发送 MSN 消息给 cppof286
默认

现在我特别想知道的是:MiniTS中是否允许通过接口在不同的程序设计语言编写的代码之间传递复杂的数据结构?例如链表、数组之类的。因为对于基本数据类型来说,这个转换处理比较简单,直接在框架内部做映射就可以了;但是对各种复杂数据结构来说,这种转换就比较麻烦了。

例如 Python-C 接口中,当程序员向 C 接口中传递一个列表时,C 接口实际接受到的总是 PyObject*,然后程序员需要使用转换操作:PyArg_ParseTuple() 来转换成 PyList*,但是当传入的类型是用户自定义的类时,Python 自己定义的转换函数就不能解析了。 所以 Python 提供的 C 接口能够接受的参数经常被限制成只能支持 Python 能够直接支持的基本数据类型,一旦需要传入复杂数据类型时就要再添加一个 Python 包装。
(当然了,我学 Python 时间还不长,上面的话我也不敢说就一定是准确的,说不定实际上 Python 有这个功能而我还不知道,如果有高手知道的话,请不吝赐教)

因为具体使用时,不同的模块的编写语言可能是不同的,它们的数据结构设计方法也不同,因此想在不同的目标语言定义的接口之间实现自动转换几乎是不可能的,所以能够选择的方法只有两种:

1. 学习Python,让程序员做高层包装,保证MiniTS系统只会接受到MiniTS能够接受的内建数据类型。这种方法比较简单,但是就在代码中引入了类似boxing和unboxing的机制,而且这样子写出来的MiniTS的参数表可能会很长,维护的时候可能不够方便。

2. 把类型定义也加入到接口规范中来,允许程序员利用标准的接口规范描述数据结构,然后把数据结构的描述用一个标准的如MiniType之类的结构封装起来。在运行时利用动态类型系统的特点,动态分析给定的参数是否能够满足要求。这种作法实际上也就是Python处理C语言设计的类时采用的方法。不过我们还可以做得更好一些:我们可以通过宏机制来让MiniTS系统自己处理类型转换问题,从而彻底根绝程序员进行自动类型转换的负担。但是这样做就需要MiniTS扩展出一个数据结构描述接口来对不同的程序语言提供的数据结构做转换。不知道达明兄是否考虑过这样的设想?
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #12 (permalink)  
旧 2005-08-08
cppof286 的头像
高级会员
 
注册日期: 2004-11-24
住址: 已经在北京了
帖子: 147
cppof286 正向着好的方向发展
发送 MSN 消息给 cppof286
默认

关于 UTF-8 的考虑嘛,我承认是有一些吹毛求疵了。这可能与我这边的工作方式有关,因为我们这里做的主要是显示层,如果有一个字符是错的后面都是对的,那么至少我可以让那个错的字符显示为<error>,而保证其它部分能够正确显示。如果说网络传输的正确性可以由TCP协议来保证的话,那么这个问题也就不复存在了。

不过我说的 GB2312 的字符不够的情况却不是胡说的。GB2312 支持的字符不足7000 个,如果只是国内应用的话倒是还可以对付,但是如果考虑让 MiniTS 走出国门,默认使用 GB2312 就比较麻烦了。另外,考虑到国家现在规定软件产品必须强制支持字符数目更多的 GB18030,默认使用 GB2312 似乎也不是一个好主意了。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #13 (permalink)  
旧 2005-08-08
高级会员
 
注册日期: 2002-10-11
帖子: 143
达明一排 正向着好的方向发展
默认 嘻嘻

因为必竟有自己的类型系统实现,多了一层,这种转换肯定是必要的。但在最终肯定还是可以想办法继续简化的,如果是C,继续简化的可能性不是很大,但如果用C++,简化成对调用方基本透明可能还是可以做到的,你说是吧?
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #14 (permalink)  
旧 2005-08-08
高级会员
 
注册日期: 2002-10-11
帖子: 143
达明一排 正向着好的方向发展
默认

  对于复杂数据类型,我也考虑过。MiniTS 的最终解决方案将是直接将C语言的结构在本地内存中映射出来,让模块根本不知道什么是 MiniTS,当然,这有相当的难度。而且可能要考虑不同的平台,不同的编译器。但目前的参数调用就是由 MiniTS 系统自己构造的参数栈,所以技术难关基本没有,主要是实现难度和工作量了。不过不管怎么说,这不是件容易的事情。

  但在目前,MiniTS 提供了一个和 Python 类似的功能。它有一个“类”的概念,这个类就是可以动态定义的用户自定义数据类型,支持单根继承,Nested Class,DownCast等一些功能,基本上目前流行的语言提供的类型定义功能它都支持,只是不支持方法调用。目前它专门用于在不同的系统之间传递用户自定义类型。对于像 C#这种语言来说,根本不知道 MiniTS 的存在,因为 MiniTS 系统已经把“类”与 .NET 的 CLR 数据类型完全合在了一起。但对于C,它没有动态类型系统,使用它的方法肯定和 Python 有些相似了。

  现在,MiniTS 已经提供了一种标准的、统一的、并且足够强大的类型类定机制,允许程序员自定义任何复杂的数据结构,系统会自动生成 MiniType。至于你文中说的“用宏机制来做数据类型转换”,实际上我的想法比这还要好,那就是上面说的,在系统内部直接构造与之兼容的内存块。因为通过宏来处理有两个不好的地方:1、是类型不安全;2、是代码还是不太自然。

你说呢?
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #15 (permalink)  
旧 2005-08-08
高级会员
 
注册日期: 2002-10-11
帖子: 143
达明一排 正向着好的方向发展
默认 另外

另外关于字符串编码,我还有一个问题要问你。

GB2312到GB1088943257 需要做编码转换吗?
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #16 (permalink)  
旧 2005-08-08
高级会员
 
注册日期: 2002-10-11
帖子: 143
达明一排 正向着好的方向发展
默认 1

引用:
作者: cppof286
例如 Python-C 接口中,当程序员向 C 接口中传递一个列表时,C 接口实际接受到的总是 PyObject*,然后程序员需要使用转换操作:PyArg_ParseTuple() 来转换成 PyList*,但是当传入的类型是用户自定义的类时,Python 自己定义的转换函数就不能解析了。 所以 Python 提供的 C 接口能够接受的参数经常被限制成只能支持 Python 能够直接支持的基本数据类型,一旦需要传入复杂数据类型时就要再添加一个 Python 包装。
哈哈!如果 Python 这种纯脚本语言对C接口都支持成这样,那 MiniTS 在这方面就比它强多乐!在 MiniTS 中,无论多复杂的数据类型都是一个 MiniObject *,而一个 MiniObject * 可以是用户自定义的任何复杂的数据类型,并且它可以自动完成远程与本地的 Marshal,哈哈哈哈!

以下就是我用C#写的测试程序中定义的数据类型,MiniTS 可以正确处理下面的
MyType 类

代码:
public class MyBaseType { public struct BaseNested { public bool base_nested_field; } public bool base_type_field; } public class MyType : MyBaseType { // 类型为基类所声明的嵌套 struct 字段 public BaseNested bn; // 以下基本数据类型是目前 Mini.NET 在 .NET 平台下支持的基本数据类型 // 这些数据类型在 Mini 服务中已经实现 public bool b; public char c; public sbyte sb; public byte bb; public short s; public ushort us; public int i; public uint ui; public long l; public ulong ul; public float f; public double d; public string ss; public DateTime dt; public TimeSpan tp; public Guid g; public byte[] bs; public class Ab { public System.Guid m_guid; } // 使用了全局数据类型的成员变量 public OtherType ot; // 一个嵌套类成员变量 public Ab cc; public class Cde { public class Efg { // 在嵌套类中使用了外部类的另外一个嵌套类做成员变量 public Ab c; } public Efg m_efg; } public Cde ccccc; } public class OtherType { public string s; }
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #17 (permalink)  
旧 2005-08-08
cppof286 的头像
高级会员
 
注册日期: 2004-11-24
住址: 已经在北京了
帖子: 147
cppof286 正向着好的方向发展
发送 MSN 消息给 cppof286
默认

我想我没有把话说明白。在 Python 当中,如果使用 C 接口编写与 Python 相容的接口时,一般普通函数需要这样来写:
代码:
PyObject * foo(PyObject *self, PyObject *args);
这个函数的接口传入的第一个参数相当于 this 指针(如果是普通就是 NULL),第二个参数是 args。Python 当然允许使用 PyObject表