原文地址:
http://blog.chinaunix.net/uid-16175364-id-2752232.html
Delphi与C++Builder代码共享的实现 2006-10-30 13:58:49

分类: C/C++

一.引言 
  在当今计算机世界中,各种编程语言琳琅满目,从Basic、Pascal到C++、Java再到汇编语言,应有尽有。 Delphi和C++ Builder可以说是Inprise公司开发的编程语言系列中的“绝代双娇”。Delphi使用的是Object Pascal语法,它具有易学易用的特性,能使初学者迅速编写出表现力极强的程序;而C++Builder对于高水平的程序员而言无疑是优秀的开发工具, 它最大程度体现了C++语言的灵活性和适用性,大大提高了程序的运行效率。如果能够把这两种语言结合使用势必会大大提高程序的开发效率。 
   其实,用户完全可以在C++Builder和Delphi之随心所欲的进行多平台程序开发,Delphi和C++Builder之间具有十分密切的关系, 他们在性能上非常相似。你用Delphi编写的任何代码几乎都可用在C++Builder中,同样用C++Builder写的部分代码也可用在 Delphi中。这样在编写程序中,程序员们就可根据自己的喜好和特长决定实用哪种语言,而不必担心使用一种语言编写的代码不会被另一种语言接受。编好之 后只要遵从一定的规则把它们连接在一起即可使用。 二.理论依据 
  Delphi语言使用了面向对象的Pascal,而C++Builder使用的语言是C++,这两种工具编写的完全不同代 码是如何连接在一起的呢?这主要是因为两者使用相同的编译器后端,编译后产生的目标文件是一致的,不同之处仅仅是前端的语言分析差异而已。Delphi的 编译速度一般要比C++ Builder快,这是由于Delphi采用了以单元为基础的编译方式,生成一种更为灵活的二进制文件-DCU格式,但是C++Builder的增量编译 方式减少了二者编译速度上的差距。其次,C++Builder的VCL控件(Visual Component Library可视构件库,简称VCL)全部由Delphi编写,因此用Delphi编写的VCL控件可直接引入C++Builder的IDE中无须作任 何改动。第三,C++与Object Pascal语言的基本数据类型非常相似,这使的在编译时二者之间进行数据传送非常方便,以下为二者的基本数据类型的比较(表-1) 
表-1. C++与Object Pascal的基本数据类型比较

C++ Object Pascal C++ Object Pascal
Unsigned Char Byte Char Char
Char A[size] Array[0..size-1] Int Integer
Unsigned int Word Long Longint
Unsigned long Longint Float Single
Double Double Char far* Pchar
Struct Record Union Record with variants
Ansistring String VARIANT Variant

   第四,二者都具有相同调用约定格式Stdcall,无论是Object Pascal还是C++都规定,凡是要输出的例程必须采用Stdcall调用约定。由于Stdcall也是Windows95/98/NT的API采用的 调用约定。因此,用户可放心地使用Stdcall调用约定共享Object Pascal、C++以及Windows95/98/NT输出的例程。以下为C++和Object Pascal各自的调用约定(表-2)。其实,从本质上讲Object Pascal是C++的一个子集。 
表-2. C++和Object Pascal的调用约定

Object Pascal C++ 默认
Cdecl Cdecl C++的默认调用约定
Pascal Pascal Delphi1.0、Windows3.x的默认调用约定
Stdcall Stdcall Windows95/98/NT的默认调用约定
Register _Fastcall Delphi2.0/3.0/4.0/5.0的默认调用约定

三. 代码共享 
  面向对象编程的基本出发点就是代码重用。要实现Delphi与C++Builder之间的代码共享显然有两种方法:一是在C++Builder中使用Delphi写的代码,二是在Delphi中使用C++Builder写的代码。下面我们就这两种方式分别加以叙述。 
  3.1. 在C++Builder中使用Delphi的代码 
   Inprise公司推出C++Builder的时间要比推出Delphi的时间短,在推出C++Builder时中已经充分考虑到了Delphi优秀特 性,因此二者在开发环境(Integrated Development Environments,简称(IDEs)、可视组件库(Visual Component Library,简称VCL)、单元文件(Form Files)和组件包(Packages)上非常相似,C++Builder的整个VCL都是用Delphi写的,因此在在C++Builder中使用 Delphi的代码要比在Delphi中使用C++Builder的代码容易地多。以下就在C++Builder中使用Delphi代码方法的具体给予阐 述: 
  3.1.1.在C++Builder中直接使用Delphi的代码 
  C++Builder并不关心你加入在工程文件中的 单元文件(Unit)是用C++Builder编写的还是用Delphi编写的,C++ Builder将编译你加入的单元文件就象编译C++Builder的代码一样,尽管C++Builder不支持Delphi的某些语法格式,例如 try…finally 和with结构等,但这些语法格式都可以在C++Builder中找到相应的替代语法,你会发现你用Delphi写的大部分代码几乎不做任何改动就可以在 C++Builder中编译。你可以在C++Builder中直接加入以下Delphi代码: 
  1.Delphi的窗体(Forms)  
  2.Delphi的单元文件(Units)  
  3.包含有过程(Procedures)、函数、常量,数组等的Delphi单元文件(Units)  
  4.Delphi的组件(Components)  
  加入方法如下: 
  1.选择C++Builder的Project | Add 菜单  
  2. 在工程对话框中选择所要加入的文件(文件扩展名为*.pas)并确定C++Builder将会为所加入的Delphi文件自动生成头文件(*.hpp),但应当注意在C++Builder中直接使用Delphi的代码,应当遵循以下基本规则: 
  1. 不能在同一个单元(Unit)中既使用C++Builder的代码又使用Delphi 的代码,必须在各自单独的单元内使用。  
  2. 不能在C++Builder中使用Delphi DCU格式的二进制文件。  
  3. 在C++Builder中打开Delphi的表单(Form)后,不能对其进行编辑,但是可以先继承该表单,再进行编辑。  
   4.如果一个应用程序其工程文件(Projectname.cpp)用C++Builder写的,即使整个应用程序98%的代码是用Delphi编制 的,该应用程序仍然为C++Builder程序。这也意味着你不可以将Delphi的工程文件放入C++Builder中来编译。  
  3.1.2. 在C++Builder中使用Delphi的组件 
   组件是Delphi、C++Builder中代码重用的基础,几乎所有的Delphi组件都可以在C++Builder中使用而无须做任何改动,毕竟整 个C++Builder的组件都是由Delphi编写的。 通以下方法在C++Builder中使用Delphi的组件: 
  1.选择C++Builder的Component | Install菜单  
  2.选择添加组件(Add Components)  
  3.选择所要加入的组件并确定  
   C++Builder将会自动重新编译CMPLIB32.DLL文件, 你所加入的组件(Component)就会显示在组件模板(Component Palette)上。然后就可以象使用C++Builder的组件一样使用该组件。切记在操纵使用该组件时一定要使用C++Builder的语法而不是 Delphi的语法。因为在添加该组件时C++Builder已经为你自动作了转换。 
  3.1.3. 通过COM和OLE在C++Builder中使用Delphi的代码 
   Delphi内建了对COM的支持,由于COM 对象具有语言和平台无关性,用Delphi创建的COM对象可以与用C++Builder、Visual Basic、Java、Visual C++、Word、Excel,等其他OLE敏感控件之间的代码共享。此外,在多层Client/Server环境中,COM对象还可以封装商业规则,为 分布式的客户提供服务。有三种基本方法可以将Delphi COM 对象连接到C++Builder中:  
  1. 使用OLE自动化或双端接口(Interfaces).  
  2. 使用Delphi 创建ActiveX控件然后在C++Builder载入此控件  
  3. 编写原始的COM 或OLE代码来连接Delphi对象  
   C++Builder内建了对前两种方法的支持,第三种方法要求具备较高的OLE知识。操纵一个自动化对象有两种方法:一是通过COM 对象的Idispatch接口,C++Builder中通过VCL函数CreateOleObject和Variant数据类型内建了对 Idispatch接口的支持,这是使用自动化对象的最简单的方法;.二是通过COM 对象的双端接口(Dual Interface),使用双端接口可以获得较快的速度,但是该方法实现起来比较困难,需要具备很深的COM理论知识,具体方法和DLL中的虚拟方法表 (Mapping Virtual Method Tables)相似,限于篇幅本文不在起具体实现细节。先假设有一个Delphi的Idispatch接口,输出以下方法: 
  ITest = interface(IDispatch) 
  [`{1746E520-E2D4-11CF-BD2F-0020AF0E5B81}'] 
  function Get_Value: Integer; safecall; 
  procedure Set_Value(Value: Integer); safecall; 
  procedure Prompt(const text: WideString); safecall; 
  property Value: Integer read Get_Value write Set_Value; 
  ... 
  end; 
  再假设这个动态连接库(DLL)已经注册并且其工程表识为"TestLib.Test"。.以下为在C++Builder 中调用该接口的Prompt过程的程序: 
  void __fastcall TForm1::Button1Click(TObject *Sender) 
  { 
    Variant V = CreateOleObject("TestLib.Test"); 
    V.OleProcedure("Prompt", "Hello World!"); 
  } 
  当然你也可以通过以上方法调用该接口中的其他过程和函数。用户应当注意在C++Builder中Variant类型并不是一个数据类型,所以在使用Variant类型时应当在工程文件中加入Sysdefs.h.。  
  3.1.4. 在C++Builder中使用Delphi的ActiveX 控件 
   C++Builder和Delphi完全支持ActiveX,您可以很方便地创建、注册、安装、发布和使用ActiveX 控件、ActiveForm和OLE自动化对象, 这应当归功于“对象接口”技术和DAX 技术。通过以下方法在C++Builder中使用Delphi 的ActiveX 控件: 
  1. 选择Component | Install 菜单  
  2. 在添加组件对话框(Install Components dialog)中选择OCX按钮  
  3. 所有已经注册的组件都会列在添加OLE控件对话框中(Import OLE Control dialog),选择所要加入的控件并确定。(如要注册注册  新控件选择Register按钮)  
  4. 新的控件会出现在已安装的组件表中,选择确定退出。  
  C++Builder自动将控件的接口文件写入LIB目录下,并且自动重新编译CMPLIB32将你的控件加入到组件模板中(Component Palette)。新控件会默认的出现在组件模板的OCX页上。 
  3.1.5. 在C++Builder中使用动态连接库来共享Delphi代码 
   Windows引入一种重要机制——DLL,即动态连接库。DLL中包含有例程和资源,可以使应用程序之间共享例程和资源。使用DLL不但可以实现C ++Builder与Delphi之间代码共享,而且还实现C++Builder与Visual C++、Visual Basic、Borland C++等其他编程工具之间代码共享。在Delphi中编写一个DLL程序非常简单,在此本文不再祥述编写DLL的具体方法,着重介绍一下如何在DLL中实 现模式Form和无模式Form。 
  外部程序要访问DLL中的模式Form,DLL中必须建立和输出访问例程。外部程序调用访问例程,访问例程去建立Form类的实例,当用户单击OK、Cancal、Abort等按钮关闭Form时,访问例程返回相应的值。下面是一个典型的访问例程示例: 
  procedure ShowModuleForm(AppHandle:Thandle):Integer; 
  begin 
    Result:=-1; 
    Application.Handle:=AppHandle; 
    with TMoudleForm.Create(Application) do 
    try 
      Result:=ShowModal; 
    finally 
      Free; 
    end; 
  end; 
   访问例程至少要有一个Thandle类型的参数,用于传递调用DLL外部程序主窗口的句柄。如果应用程序是用Delphi开发的,就是 Application.Handle 。访问例程首先创建Form类的实例,然后调用ShowModal显示这个Form,最后调用Free删除这个Form实例。当然,根据不同的需要,访问 例程可以增加若干参数。在上例中,访问例程首先把返回值设为-1,这样即使Form类的实例没有创建成功,返回值总是一个确定数。函数最终的返回值由 ShowModal返回的。最后不要忘记在DLL中输出访问例程。 
  所谓无模式Form,就是即使Form没有关闭,用户也可以把输入焦点 移到其它窗口。要访问DLL中的无模式Form,DLL中需要建立和输出两个访问例程,一个用于创建Form类的实例和显示Form,另一个用于关闭 Form和删除类的实例。其它规则与访问模式Form基本相同。一个典型的创建和显示无模式Form的访问例程示例如下: 
  function CreateAndShow(AppHandle:THandle):Integer ; 
  var MyHandle:THandle; 
  begin 
    Application.Handle:=AppHandle; 
    MyHandle:=THandle(TNon-ModalForm.Create(Application)); 
    {创建TNon-ModalForm类的实例,并强制转换为THandle类型} 
    Result:=MyHandle;{把Form的句柄作为返回值} 
    with TNon-TMoudleForm(MyHandle) do 
    try 
      Show; 
    except 
      Free; 
      Result:=0; 
      Raise; 
    end; 
  end; 
  一个典型的关闭和释放类实例的访问例程示例如下: 
  procedure CloseAndFree(FormHandle:THandle); 
  begin 
    if FormHandle=0 then 
      Raise Exception.Create('Form类的实例没有创建!'); 
    else 
      with TNon-ModalForm(FormHandle) do 
      begin 
        Close; 
        Free; 
      end; 
  end; 
  我们也可以把类写成DLL,然后被其它程序或DLL共享,但要注意不能直接使用DLL中的类的方法和成员,而只能调用DLL中输出的类。同样DLL中也可以包含虚拟类,但是实现起来比较麻烦,限于篇幅本文不再叙述。 
  3.2.在Delphi中使用C++Builder的代码 
   从本质上讲Object Pascal是C++的一个子集,因此在Delphi中使用C++Builder的代码要比在C++Builder中使用Delphi的代码困难的多。在 Delphi中直接使用C++Builder的代码几乎是行不通的,但是由于OLE、COM、DLL都是Windows系统的规范,因此可以通过这三种方 法很方便在二者之间实现代码共享。在Delphi中通过这三种方法来使用C++Builder的代码和在C++Builder中通过这三种方法来使用 Delphi代码基本相同,在此本文不在另行叙述。 
  尽管Delphi也支持OBJ文件,在Delphi中连接C++Builder的 OBJ文件也很简单,只要用{$Link}或{$L}指示字指定要连接的OBJ,其格式为:{$L 文件名},但是Delphi的程序只能访问OBJ中很简单的例程。用户既不能访问OBJ中C++的类,也不能访问C++的RTL(运行期库),也不能访问 C++的几个全局变量。也就是说如果例程中包含对TRL的调用或者对Windows API的调用,或者OBJ中包含C++类的声明,Delphi的链接器都将失败。因此在Delphi中用C++的OBJ几乎没有任何实用价值。 
四.结论 
   本文详细叙述了实现C++Builder与Delphi代码共享的各种方法,通过比较可以发现在C++Builder中共享Delphi的代码,要比在 Delphi中共享C++Builder的代码容易得多。但是通过DLL、OLE和COM我们也可以很方便的在Delphi中共享C++Builder 的代码。 
  此外,还可以使用一些中间层方式来实现C++Builder和Delphi之间代码共享,所谓中间层方式是指将C++ Builder的代码和 Delphi的代码分开编译成两个可执行模块,然后通过中间层实现两个模块的数据共享和相互操纵。中间层可以是剪贴板、DDE、磁盘文件、BDE以及 Windows的消息。不过这已经不是真正意义上的代码共享了,只是程序间的数据交换,因而使用这种结构的程序执行速度比较慢,如果对程序执行的速度要求 不是很高,也可以考虑使用中间层结构。 
  综上所述,我们发现在C++Builder和Delphi之间实现代码的共享是比较容易的事,不过 实现的难度有所不同,在C++Builder中共享 Delphi的代码要比在Delphi中共享C++Builder的代码要容易一些,因此我们提倡尽量用C++Builder建立工程文件,充分利用两种 语言各自的优点,在C++Builder中共享Delphi的代码,以加快整个软件开发的速度

Delphi与C++Builder代码共享的实现相关推荐

  1. Delphi 和 C++Builder 免费社区版更新至 10.4.2 版现已发布!

    Delphi 和 C++Builder 的免费且功能齐全的社区版旨在帮助您开始编程.这些强大的 IDE 提供了快速探索强大的应用程序开发所需的所有功能. 社区版发布后,社区中的学生和爱好者可以免费使用 ...

  2. android 共享代码,Android团队成员间的代码共享!(Git+Github版)

    原创,转载请说明出处. 一. 这篇文章要解决什么问题,能学习到什么? 在android团队的开发中,少不了与队员之间的合作.为了避免我们傻瓜式地复制粘贴对方的负责的那部分功能代码,我们可以用svn或者 ...

  3. 包r语言_R语言代码共享:制作R包

    作者:黄天元,复旦大学博士在读,热爱数据科学与开源工具(R),致力于利用数据科学迅速积累行业经验优势和科学知识发现,涉猎内容包括但不限于信息计量.机器学习.数据可视化.应用统计建模.知识图谱等,著有& ...

  4. ArcGIS Engine代码共享-可以直接移植到你的工程中

    以前写ArcGIS Engine程序,都是一些代码积累,基本上都是静态变量,如果有基础的一看就明白了,我也没有时间来总结这一块了,大家自己消化吧,好多东西应该可以直接移植到其他地方. ArcGIS E ...

  5. 微信小程序自定义组件4 —— 代码共享behaviors

    behaviors 用于实现组件间代码共享 每个behavior可以包含一组属性.数据.生命周期函数和方法.组件引用behavior时,它的属性.数据.和方法会被合并到组件中 每个组件可以引用多个be ...

  6. 350 个在家办公的人,创造了估值 10 亿美元的代码共享平台

    [CSDN编者按]每一年都有无数的科技公司前往硅谷创业,梦想着一夜暴富.人生翻盘,但鲜少有人能不走弯路.本文中分享了一个经典的故事:9个人想出了一个绝佳的计划--他们仅用了三年时间就让员工人数达到了3 ...

  7. 美通社企业新闻汇总 | 2019.2.1 | 迪士尼推出猪年限定产品;阿联酋航空与南航签订代码共享协议...

    要闻 和睦家健康选礼指南:春节如何为长辈买好礼 迪士尼贺新春,推出猪年限定产品 阿联酋航空与中国南方航空签订代码共享协议 索理思和巴斯夫已完成造纸和水处理化学品业务的合并 JNA珠宝设计大赛2018/ ...

  8. RAD Studio Delphi、C++Builder 11 即将推出:新版本号公告和更新订阅客户的 Beta 版邀请

    我们很高兴地宣布,Delphi.C++Builder 和 RAD Studio 的下一个版本将是版本 11.目前正在开发中,我们计划在今年晚些时候发布. 转移到版本 11 几年前,Embarcader ...

  9. 阿联酋航空与中国南方航空签订代码共享协议

    总部位于迪拜的国际航空公司阿联酋航空(IATA代码:EK)和总部位于广州的中国南方航空公司(IATA代码:CZ)近日正式签署了一份合作谅解备忘录,以达成全面互惠的代码共享合作协议,为从中国前往中东和非 ...

最新文章

  1. Yii 框架调试之CWebLogRoute
  2. 将Unreal4打包后的工程嵌入到Qt或者桌面中
  3. Lucene mysql app查询_集成Lucene,查询相关数据
  4. android home键后计时拉起app_使用React Native完成App软件
  5. FFmpeg中MPEG-4编码程序追踪,其他FFMPEG自带编码器同理
  6. Flask入门系列(转载)
  7. 信源压缩编码 编程c语言,霍夫曼信源编码实验报告.docx
  8. 缺陷管理系统mantisbt环境搭建
  9. 360 nginx+php,windows Nginx+PHP7+Mysql独立环境部署
  10. 筛选法求素数-c++
  11. t分布 u分布 卡方分布_F分布、t分布、正太分布与卡方分布的联系与区别
  12. JAVA 如何反编译JAR文件
  13. 多任务学习-Multitask Learning概述
  14. 乱世王者服务器维护,乱世王者微信534区仰不愧天开服时间表_乱世王者新区开服预告_第一手游网手游开服表...
  15. wex5 checkbox
  16. HDU-1546-Idiomatic Phrases Game
  17. YoloV5 训练长方形图像
  18. 电路板上的黑色小圆“疙瘩”到底是什么?有什么用?
  19. 什么是你的核心竞争力之六正视你的弱点
  20. 简单字符驱动笔记(朱有鹏)

热门文章

  1. JS 兄弟元素和兄弟节点
  2. 用HK-MSR165微型振动冲击记录仪记录动态机械应力,帮助优化机器、工件和生产
  3. 反射机制:getDeclaredField和getField的区别
  4. ceilometer + gnocchi 获取数据
  5. Vikings V2用户手册
  6. Matreya / 艾美捷 葡萄糖脑苷标准品
  7. java医药管理系统
  8. python scrapy框架爬取豆瓣top250电影篇一Windows下建立Scrapy项目,pycharm编辑
  9. CFF 1022 平均年龄
  10. swagger2、rap2与YAPI