C++Builder, 1, Borland C++Builder White Paper: Application Development with C++Builder and Delphi

By: Borland Staff

Abstract: C++Builder and Delphi have a unique relationship that allows programmers to easily share code between the two environments.

Application Development with C++Builder and Delphi
Written by Charlie Calvert

Note: The views and information expressed in this document represent those of its author(s) who is solely responsible for its content. Borland does not make or give any representation or warranty with respect such content.

Overview

C++Builder and Delphi have a unique relationship that allows programmers to easily share code between the two environments. Almost anything you write in Delphi can easily be used in C++Builder, and much of the code you write in C++Builder can be used in Delphi. As a result, programmers can work in either C++ or Delphi, depending on their skill level or inclination.

Despite their similarity, Delphi and C++ each have a unique set of capabilities:

  • Delphi's ease of use allows a wide range of programmers to quickly produce high performance, robust components, objects or applications.
  • C++Builder, in the other hand, allows the best programmers on your staff to write code in a language known for its power and wide acceptance.

Because you can share code between the two environments, you can allow your staff to use the tools that best suit their current needs. Then later on, you can swap the code back and forth between the two environments.

This paper is divided into two main sections. The first part contains an executive summary suitable for the general reader. The second, and longer, section of the paper contains a more technical analysis of the methods for sharing code between C++Builder and Delphi.

Benefits of Sharing Code Between C++Builder and Delphi

This section lists some of the key benefits gained when you share code between Delphi and C++Builder. These items are listed in no particular order.
  • Programmers can work in either C++ or Delphi. You don't have to worry that code written with one tool will not be accessible from inside the other tool. Instead, you can concentrate on finding the fastest way to create usable modules, and then link them in to either C++Builder or Delphi, depending on the needs of your engineers.

  • Sharing code between Delphi and C++Builder also promotes code reuse. You can write an object once for a Delphi project, and then reuse it, unchanged, in a C++ project. There is no performance or size penalty associated with writing code in Delphi rather than C++.

  • Delphi is extremely easy to use. It offers programmers a simple, easy to understand syntax. Companies can allow programmers to work in Delphi without fear that their code cannot also be used in C++ projects. You can therefore have some of your team working full time in C++, and the rest of the team working full time with the much easier to use Delphi language. The efforts of both programmers can then be combined into a single, high performance executable.

  • Because Delphi is so easy to use, it is often the language of choice during projects that have tight deadlines. Use Delphi to create high performance programs as easily as possible. Any modules or objects created on these types of projects can then later be linked into C++ projects. This means that there is no penalty associated with using Delphi inside your company, even if you are primarily a C++ shop.

Technical Highlights

This section of the paper contains an overview of the key points you need to know about sharing code between C++ Builder and Delphi. It consists of two subsections called:
  1. Overview: Using Delphi Code in C++Builder
  2. Overview: Using C++ Code in Delphi

When you are through reading these sections you will have a general feeling for how, and to what degree, you can share code between Delphi and C++Builder. In subsequent sections I will review most of these points in more detail.

Before beginning, you should note that Delphi uses Object Pascal, which is widely taught in many schools. C++Builder uses C++, which is probably the most widely used language in corporate America. Most programmers will know one, if not both, of these languages.

Overview: Using Delphi Code in C++Builder

C++ Builder does not care whether the units you add to your project are written in C++ or in Delphi. It will compile either type of unit as if it were native to C++ Builder.

As a general rule, any Delphi 2.01 unit you create that compiles in Delphi compiles unchanged in C++Builder. There are a very few Delphi syntactical elements that will not be accepted by C++Builder. You will generally find that all your Delphi 2.01 or Delphi 2.0 code will compile unchanged in C++Builder. This is an unprecedented level of seamless integration between Delphi and C++.

In particular, the following types of code will compile in C++Builder:

  1. Delphi forms.
  2. Delphi units containing objects.
  3. Delphi units containing procedures, functions, constants, structures, arrays, etc.
  4. Delphi components.

You usually do not have to change your Delphi units at all to link them in to C++Builder. There is no need to change the code, to create header files, or to massage your code in any way. You can mix the types of code listed above in any way you like. For instance, you can link into C++Builder one Delphi unit that contains:

  • A form
  • An object
  • Some functions
  • A component

The unit can contain any combination of the above types, or of any other valid Pascal types. These types may appear in any combination. For instance, a Pascal unit can contain only an object, or it could contain, both an object and a form, etc. You can link in as many Pascal units as you like, each containing any combination of the above objects. There is no limit on the number of Delphi units you can add to a C++Builder project.

To link Delphi code into C++Builder you simply choose Add to Project from the menus, then browse for files that end in PAS. Once you have added one or more Delphi units to your project, they will compile and link seamlessly with the rest of your C++ code. Use Visual Form Inheritance to modify Delphi forms within C++Builder. You can resynchronize when updates are made to the original Delphi form.

Besides the simple techniques outlined above, advanced programmers can also link Delphi code into C++ by using one of the following techniques:

  1. Delphi dynamic link libraries (DLLs), can be easily added to your C++ projects.
  2. You can use COM and OLE to add Delphi 2.0 or Delphi 3.0 objects to C++Builder. In particular, you can add Delphi objects to C++ Builder via:
      a.OLE Automation b.The basic rules of COM c.Creating Delphi ActiveX controls that you use in C++Builder.
  3. Delphi and C++Builder share the same Virtual Method Tables (VMTs). This means you can create an object in Delphi, and use it in C++ Builder via a technique outlined below in the section called "Mapping Virtual Method Tables"

Overview: Using C++ Code in Delphi
C++ supports some syntactical elements such as multiple inheritance and function overloading that make it difficult to directly link all C++Builder code into Delphi. However, you can still share code between the two environments via:

  1. COM and OLE. Delphi fully supports both OLE Automation and dual interfaces.
  2. DLLs
  3. Direct linking of C++Builder units containing functions.

The most convenient technique listed above is the first, especially if your C++ COM objects support type libraries. Delphi 97 has full support for type libraries, and will be able to generate Delphi units directly from a type library. This means that you can link C++ COM objects that support type libraries directly into Delphi without having to write any extra code. All the necessary files for linking in C++ COM objects that support type libraries will be generated automatically by Delphi.

DLLs are a powerful means of sharing code between Delphi and C++ Builder. Virtually any C++ Builder function that you create can be placed in a DLL and called directly from Delphi. Delphi supports all the common calling conventions such as CDECL, PASCAL, and STDCALL. You can access an object written in C++ from inside Delphi simply by reversing the technique described below in the section entitled "Mapping Virtual Method Tables".

It is possible to link C++ OBJ files directly into Delphi. This is a powerful technique that can be very useful in certain circumstances. However, their are limitations on what you can do with this technology, and it should not be viewed as a primary means of porting code between the two environments.

Summary of the Executive Overview

Before closing this section of the paper, it might be helpful to review some of the key points mentioned so far. This will complete the executive summary for non-programmers who do not wish to delve into the technical details involved in linking code between the two environments.

C++Builder has virtually no limitations on it's ability to use Delphi code. You can simply link your Pascal units directly into C++Builder without modifying them in any way. They will then compile into the same small, tight, high-performance machine code you would expect if you wrote them in C++.

If you use both C++Builder and Delphi in a single project, you can promote code reuse while simultaneously leveraging the skills of all your programmers. C++ engineers can work in C++ where they can take advantage of that language's power and control. Where tight deadlines, ease of use, and a short learning curve drive development, programmers can work in Delphi.

Together, C++Builder and Delphi developers are an extremely productive team — combining their efforts and code while working within the development environments best suited to their skills, preferences, and projects.

The key point is that the technology outlined in this paper allows your programmers to work in either C++ or Delphi, without fear that the code will not be available for use in all your C++ projects.

A More Technical Analysis
You have now completed the overview of the techniques for sharing code between C++Builder and Delphi. The remaining sections in this paper explore these subjects in more depth. In other words, if you are a manager, you can now put this paper down and go on to something else. If you are a programmer, this is where the paper starts to get interesting. The subject matter in the following sections starts out with the simplest techniques, and becomes increasingly complex as the paper nears its conclusion.

Ground Rules for Linking Delphi Code into C++ Builder
You have already learned that you can link Delphi code directly into C++Builder projects. In this section I will explain how this is possible, and put to rest any fears you might have about engaging in constructing this kind of project.

First, I will lay down three key ground rules.

  1. You cannot mix C++ and Delphi code in the same unit. You have to create separate units (modules) for each type of code.
  2. You must have the source to the unit you want to use. You cannot link a Pascal binary file (DCU) into a C++Builder project.
  3. You cannot edit a Pascal unit while it is open in C++Builder.

Furthermore, you should note that a Pascal unit cannot usually be the project file for a C++Builder application. However, if this one, small module is written in C++, and everything else in the project is written in Object Pascal, then the project is still, by definition, a C++Builder project, even though the code is ninety-eight percent written in Object Pascal.

Here is a detailed description of the simple steps need to link a Delphi unit into a C++Builder project:

  1. First choose the Project | Add to Project menu option.
  2. When the Add to Project dialog appears pull down the Files of Type combo box at the bottom of the dialog. You will then be able to select files of type CPP, PAS, C, RES, OBJ or LIB. You should select PAS.
  3. Browse for the Pascal source file you want and add it to your project. After you have selected the file you want to use, you can click on OK to add it to your project and proceed exactly as you would if this were a C++ file.

The header file for your unit will be generated automatically. You don't have to do anything to the unit to use it in a C++Builder project. Linking a Delphi Component into a C++Builder Projec
If you want to use a Delphi component in a C++ project, you would normally want to first add it to the Component Palette. You do this via the same basic technique you would use in Delphi. In particular:

  1. Choose Component | Install from the menu.
  2. Select the Add button from the Install Components Dialog
  3. Use the Add Module dialog to enter or browse for the name of the PAS file you want to use, that is, for the PAS file that contains the registration procedure for your Delphi component.
  4. After selecting the module, click on the OK button in the Install Components dialog. C++Builder will then recompile CMPLIB32.DLL, thereby adding your component to the Component Palette.

After you have integrated a Delphi component into C++Builder, you can then treat it exactly as if it were a native C++Builder component. That is, you can drop it onto a form and manipulate its methods with the object inspector. If you need to reference any of the components methods in your C++ code, then you should use C++ syntax. The details of this syntax can be surmised by viewing the header file created when you added the component to the Component palette.

Some Theory on Linking Object Pascal and C++Builder Code

Delphi is an Object Pascal based development environment, while C++Builder is obviously a C++ based development environment. How is it possible to link Pascal directly into a C++ project?

A good way to begin your exploration of this issue is to understand that Delphi, and Borland C++ 5.0 use the same 32-bit compiler. The difference is simply in how the language is parsed. Delphi parses Object Pascal, tokenizes it, and then passes it on to the compiler. Borland C++ 5.0 parses C++, tokenizes it, and then passes it on to the compiler. Underneath the hood, Delphi 2.0, C++ Builder and Borland C++ are very similar tools. The difference is in how the syntax of the language looks before it is parsed and tokenized.

Delphi finishes its compile and link cycles faster than Borland C++ simply because Pascal is easier to parse, and because Delphi supports a simpler, and more flexible type of binary file (DCUs are easier to make than OBJs.)

Since C++Builder uses the same compiler as Delphi, the road is obviously at least half way open to finding compatibility between Delphi and C++. The next stone on the path is laid by C++Builder's advantageous use of the Delphi VCL.

C++Builder uses the Delphi VCL in all of it's standard projects. It therefore needs to understand Delphi's types, objects and syntax. This was made possible in part by the fact that Object Pascal is similar in structure to C++, but supports a subset of the features available in C++. (There are some features of Object Pascal, such as sets, not supported by C++, but these are relatively minor roadblocks that can be overcome through a judicious use of templates and classes.)

The converse of the logic in the last paragraph is not true. There is no need for Delphi to parse C++. Furthermore, Object Pascal is, in a sense, a subset of C++. It is therefore easier for C++Builder to adopt to the features of Delphi, than it is for Delphi to support certain esoteric features of C++ such as multiple inheritance, variable parameter lists, or function overloading.

Object Pascal is not radically different from C++ in the sense that BASIC is radically different from C. The two languages, Object Pascal and C++, share the same structure.

C++Builder and Delphi share a common heritage in the way they construct objects, handle variable types, and define methods. In particular, a Delphi object's VMT is identical in structure to a C++ object that uses single inheritance. Furthermore, Delphi supports all the calling conventions, such as CDECL, PASCAL, and STDCALL, that are used with C++ functions and methods. Therefore, there is no difference in the structure of a Delphi function or method and a C++ function or method. They look the same on the assembler level, so long as C++ is not using any "advanced features", such as function over loading or variable parameter lists. (Remember that by default, Pascal uses the fastcall calling convention, which means that it passes some parameters to functions in registers. This same convention is supported by C++ Builder, or you can explicitly use a different convention if you like.)

Finally, there is a direct parallel between most C++ types and the standard Delphi types. For instance, a C++ int is identical to a Delphi Integer. Other types, such as strings, are either identical, or very similar. For instance, a C++ char * (LPSTR) is identical to a Delphi PChar. Furthermore, a Delphi string is fully compatible with a char *, and the C++Builder AnsiString type is designed to be compatible with, and to mimic, a Delphi string. This parallel structure continues throughout the two languages, and includes complex types such as structures (records) and arrays. (What C++ calls a union, Delphi calls a variable record.)

There are, however, some differences between the languages. For instance, Delphi does not support templates, C++Builder does not support sets, and each language implements exception handling and RTTI slightly differently. These differences are significant, but they do not represent an impenetrable barrier erected between Delphi and C++Builder.

In this section you have seen that Delphi and C++Builder both use the same compiler, and support a very similar syntax and style of programming. These are the key elements that make it possible to share code between C++Builder and Delphi.

Server Response from: SC2