|
Author: Javier Miranda, Arnaud Charlet, AdaCore
Abstract: Ada Gem #61 — In the previous Gem about generating bindings from C++ headers, we mentioned, without going into details, how to interface with C++ constructors in Ada using the CPP_Constructor pragma.
In this Gem we present some common uses of C++ constructors in mixed-language programs in GNAT, and in the next Gem, we will show the use of some powerful Ada 2005 features in conjunction with C++ constructors.
Let’s assume that we need to interface with the following C++ class:
class Root {
public:
int a_value;
int b_value;
virtual int Get_Value ();
Root(); // Default constructor
Root(int v); // 1st non-default constructor
Root(int v, int w); // 2nd non-default constructor
};
Using the automatic binding generator, or writing manually, we can obtain the corresponding package spec:
with Interfaces.C; use Interfaces.C;
package Pkg_Root is
type Root is tagged limited record
A_Value : int;
B_Value : int;
end record;
pragma Import (CPP, Root);
function Get_Value (Obj : Root) return int;
pragma Import (CPP, Get_Value);
function New_Root return Root'Class;
pragma Cpp_Constructor (New_Root, "_ZN4RootC1Ev");
function New_Root (v : int) return Root'Class;
pragma Cpp_Constructor (New_Root, "_ZN4RootC1Ei");
function New_Root (v, w : int) return Root'Class;
pragma Cpp_Constructor (New_Root, "_ZN4RootC1Eii");
end Pkg_Root;
On the Ada side, the constructor is represented by a function (whose name is arbitrary) that returns the class-wide type corresponding to the imported C++ class. The return type is required to be class-wide rather than the specific Root type so that the function will not be treated as a primitive dispatching operation of the type. Although the constructor is described as a function, it is typically a procedure with an extra implicit argument (the object being initialized) at the implementation level. GNAT issues the appropriate call, whatever it is, to initialize the object.
Constructors can appear in the following contexts:
- As the initialization expression of an object of type T
- As the initialization expression of a record component of type T
- In a limited aggregate
- In a limited aggregate used as the expression of a return statement
Note that all of the above contexts are places where Ada 2005 allows limited aggregates and calls to functions with limited results to appear, and in fact it’s necessary to enable the Ada 2005 compilation mode (-gnat05) to make use of this feature.
In a declaration of an object whose type is a class imported from C++, either the default C++ constructor is implicitly called by GNAT, or else the required C++ constructor must be explicitly called in the expression that initializes the object. For example:
Obj1 : Root; Obj2 : Root := New_Root; Obj3 : Root := New_Root (v => 10); Obj4 : Root := New_Root (30, 40);
The first two declarations are equivalent: in both cases, the default C++ constructor is invoked (in the former case the call to the constructor is implicit, and in the latter case the call is explicit in the object declaration). Obj3 is initialized by the C++ nondefault constructor that takes an integer argument, and Obj4 is initialized by the nondefault C++ constructor that takes two integers.
It’s worth pointing out that normally it’s not permitted to call a class-wide function to initialize an object of a specific type, and it’s only in the case of these special imported constructor functions that the compiler allows this usage.
In the next Gem we will explore how to derive and extend imported C++ classes on the Ada side, and show uses of constructors in Ada 2005 extended return and limited aggregates.
Posted
in Ada / Ada 2005, Development Log, Devt log - Gem of the Week
If you have an idea for a Gem you would like to contribute please feel free to contact us at: gems@adacore.com
Anh Vo said:
Thanks for these GEMs dealing with external languages such specially C/C++.
The following comment has nothing to do with content but with the display regarding apostropy “‘”. In fact, apostropy is not displayed correctly as intended such as in function specification function New_Root return Root'Class; for example. Instead, the ' string is display. According to http://www.w3.org/TR/xhtml1/#C_16, ' should be used instead of '
Anh Vo said:
Sorry I made a typo in “Instead, the ' string is display”. It should be displayed.
Arnaud Charlet said:
Thanks for the comment. Strangely enough, the ‘ appears fine on e.g. my side. I guess it depends on your browser.
Anyway, I’ve made your suggested change (apos -> amp).
Anh Vo said:
I am using Micro$oft Internet Explorer Version 6.0. The exact version is 6.0.2900.2180.xpsp_sp2_qfe.080814-1242.
Your fix did not seem to change the display. In fact, ' is displayed still. As a test, I copied the source of this page. Then, I replaced every occurrence of ' by '. Finally, I opened it with explorer. The apostropy was displayed correctly as expected.
Anh Vo said:
I just tested it on FireFox. The apostropy was displayed correctly.
Dave Elliot said:
It looks apos is an XML form (not in the HTML 4 standard). The character code 39 has to be used for Internet Explorer. It appears here that IE is following the standard closer.