.. _EAG.types: Types and Extensions ======================================= In this section we learn more about the relationship between types in KL and corresponding types in extensions. The header file generated by :command:`kl2edk` as well as the :file:`FabricEDK.h` header file it includes provide definitions for the built-in KL types, any types defined by the extension, and any types defined by other extensions required by the extension. All of these types are defined in the :code:`Fabric::EDK::KL` namespace. .. note:: For brevity, all types in this section will be referred to without the ``Fabirc::EDK::`` namespace prefix as if the :code:`using namespace Fabric::EDK;` directive had been issued. .. _types.simple: Simple Types ---------------- The simple types are all simply aliases for existing C++ types. When a simple type is passed as an :code:`in` parameter from KL, the corresponding parameter in C++ should be a "pass-by-value", ie. without the ``&`` pass-by-reference symbol. Similarly, an extension function that returns a value that is a simple type should just return the value directly rather than use a "hidden return parameter". See :ref:`cconv.simple` for more information about the calling convention for simple types. ``KL::Boolean`` The KL ``Boolean`` type. You can assign the C++ constants ``true`` and ``false`` to expressions of this type. ``KL::UInt8``, ``KL::SInt8``, ``KL::UInt16``, ``KL::SInt16``, ``KL::UInt32``, ``KL::SInt32``, ``KL::UInt64``, ``KL::SInt64`` The KL integer types; equivalent to the KL types of the same name. ``KL::Float32``, ``KL::Float64`` The KL floating-point types; equivalent to the KL types of the same name. ``KL::Byte``, ``KL::Integer``, ``KL::Index``, ``KL::Size``, ``KL::Scalar`` KL built-in type aliases; they alias the same type as in the KL language. ``KL::Data`` The KL :code:`Data` type. This is simply a type alias for :code:`void *`; however, there is a :code:`KL::DataWrapper` template provided by :file:`FabricEDK.h` that makes it much easier to work with these pointers; see :ref:`EAG.types.data` for more information. .. _types.simple.equivalent: Equivalences for Simple Types ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Since simple types are just aliases for preexisting C++ types, you can use corresponding C++ types in place of them wherever convenient. The following table shows equivalent C++ types for each KL simple type: +--------------------+------------------------------------------+ | KL Type | Equivalent C++ type(s) | +--------------------+------------------------------------------+ | ``KL::Boolean`` | ``bool`` | +--------------------+------------------------------------------+ | ``KL::UInt8`` | ``uint8_t``, ``unsigned char`` | +--------------------+------------------------------------------+ | ``KL::UInt16`` | ``uint16_t``, ``unsigned short`` | +--------------------+------------------------------------------+ | ``KL::UInt32`` | ``uint32_t``, ``unsigned int`` | +--------------------+------------------------------------------+ | ``KL::UInt64`` | ``uint64_t``, ``unsigned long long`` | +--------------------+------------------------------------------+ | ``KL::SInt8`` | ``int8_t``, ``char`` | +--------------------+------------------------------------------+ | ``KL::SInt16`` | ``int16_t``, ``short`` | +--------------------+------------------------------------------+ | ``KL::SInt32`` | ``int32_t``, ``int`` | +--------------------+------------------------------------------+ | ``KL::SInt64`` | ``int64_t``, ``long long`` | +--------------------+------------------------------------------+ | ``KL::Float32`` | ``float`` | +--------------------+------------------------------------------+ | ``KL::Float64`` | ``double`` | +--------------------+------------------------------------------+ .. _EAG.types.data: The :samp:`KL::DataWrapper<{Ty}>` and :samp:`KL::ConstDataWrapper<{Ty}>` Templates ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In order to simplify use of the :code:`KL::Data` type, :file:`FabricEDK.h` provides the templates :samp:`KL::DataWrapper<{Ty}>` :samp:`KL::ConstDataWrapper<{Ty}>` that allows you to treat a value of type :code:`KL::Data` as if it were a pointer to a more complex type. :samp:`KL::DataWrapper<{Ty}>` allows modification of the resulting complex type whereas :samp:`KL::ConstDataWrapper<{Ty}>` allows it only to be read. The best explanation is through an example: .. code-block:: C++ struct SomeMoreComplexStruct { InternalValue value; // .... }; FABRIC_EDK_EXPORT void MyFunc( Fabric::EDK::KL::Data::IOParam data ) { Fabric::EDK::KL::DataWrapper complexStruct( data ); if ( !complexStruct ) { // Note that this assignment actually changes the referenced complexStruct = new SomeMoreComplexStruct; complexStruct->value = // ... whatever } } .. _types.complex: Complex Types --------------- The complex types do not correspond directly to an existing C++ type, but instead have a complex representation as a C++ class or template in header file generated by :command:`kl2edk` or the :file:`FabricEDK.h` header file. Complex types must always be passed by reference in C++ functions corresponding to KL functions, even when they are :code:`in` parameters in KL; similarly, they must always be returned through a "hidden return parameter". This is usually done using the :code:`::INParam` and :code:`::Result` typedefs. For more information, see :ref:`cconv.complex`. .. warning:: Unlike KL (in guarded mode), there are generally no checks for array indices or other lookups when using complex types. It is the responsibility of the programmer to ensure that these operations are within bounds. .. _types.string: :code:`KL::String` ^^^^^^^^^^^^^^^^^^^^^^^ Provides the functionality of the KL ``String`` type. It supports the usual empty constructor, copy constructor, and assignment operator, as well as following methods: .. cpp:function:: const char *KL::String::c_str() const Returns the string contents as a C-style null-terminated string. .. cpp:function:: const char *KL::String::data() const Returns the string contents as a raw pointer to character data. .. cpp:function:: uint32_t KL::String::length() const Returns the string contents as a raw pointer to character data. .. cpp:function:: void KL::String::append(char ch) Appends a character to the string. .. cpp:function:: void KL::String::operator +=(char ch) Alias for ``void KL::String::append(char ch)``. .. cpp:function:: void KL::String::append(char const *data, uint32_t length) Appends another string given as a raw character pointer and a length. .. cpp:function:: void KL::String::append(char const *cStr) Appends another string given as a C-style null-terminate string. .. cpp:function:: void KL::String::operator +=(char const *cStr) Alias for ``void KL::String::append(char const *cStr)``. .. cpp:function:: void KL::String::append(KL::String const &that) Appends another :code:`KL::String`. .. cpp:function:: void KL::String::operator +=(KL::String const &that) Alias for ``void KL::String::append(KL::String const &that)``. .. _types.container: :samp:`KL::VariableArray<{Ty}>` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Provides the functionality of a variable array of the type :samp:`{Ty}`, which must itself be a KL type. It supports an empty constructor that constructs an empty array, a copy constructor and assignment operator that take a reference to the contents of the other array, as well as the following methods: .. cpp:function:: uint32_t KL::VariableArray::size() const Returns the size (length) of the array. .. cpp:function:: void KL::VariableArray::resize( uint32_t newSize ) Resize the array. The new elements (if any) will be initialized using the constructor for the given type. .. cpp:function:: void KL::VariableArray::push_back( Ty const &t ) Append an element to the end of the array .. cpp:function:: Ty const &KL::VariableArray::operator[]( uint32_t index ) const The read-only array indexing operator. .. cpp:function:: Ty &KL::VariableArray::operator[]( uint32_t index ) The read-write array indexing operator. It returns a modifiable reference to the given element of the array. .. note:: Unlike KL, there is no checks for array indices when indexing into an array. It is the responsibility of the programmer to ensure that the array index is within bounds. .. note:: References returned from the array indexing operators should be considered temporary and should not be stored in other variables. Calling the ``resize`` method on a variable array may cause references to become invalid. :samp:`KL::FixedArray<{Ty}, {size}>` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Provides the functionality of a KL fixed array of the type :samp:`{Ty}`, which must itself be a KL type, of size :samp:{size} which must be an unsigned integer. It proves the usual empty and copy constructors and assignment operators. It provides the following specialized constructors and methods: .. cpp:function:: Ty const &KL::ExternalArray::operator[]( uint32_t index ) const The read-only array indexing operator. .. cpp:function:: Ty &KL::ExternalArray::operator[]( uint32_t index ) The read-write array indexing operator. It returns a modifiable reference to the given element of the array. :samp:`KL::ExternalArray<{Ty}>` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Provides the functionality of a external array of the type :samp:`{Ty}`, which must itself be a KL built-in or user-defined type. It allows you to construct a new array from a raw pointer and element count, along with the usual empty and copy constructors and assignment operators. It provides the following specialized constructors and methods: .. cpp:function:: KL::ExternalArrayExternalArray( Ty *members, uint32_t size ) Constructs a new external array from a raw pointer and a size (element count). The external array does *not* take ownership of the data; it is the responsibility of the extension author to manage the lifecycle of the underlying data and to ensure that it outlives any use of the data anywhere in |FABRIC_PRODUCT_NAME|. .. cpp:function:: uint32_t KL::ExternalArray::size() const Returns the size (length) of the array. .. cpp:function:: Ty const &KL::ExternalArray::operator[]( uint32_t index ) const The read-only array indexing operator. .. cpp:function:: Ty &KL::ExternalArray::operator[]( uint32_t index ) The read-write array indexing operator. It returns a modifiable reference to the given element of the array. .. warning:: Unlike KL, there is no checks for array indices when indexing into an array. It is the responsibility of the programmer to ensure that the array index is within bounds. :samp:`KL::Dict<{KeyTy}, {ValueTy}>`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Provides the functionality of a dictionary that maps keys of type :samp:`{KeyTy}` to values of type :samp:`ValueTy`. :samp:`{KeyTy}` must be either a simple type or :code:`KL::String`; :samp:`ValueTy` can be any KL type. It supports an empty constructor that constructs an empty dictionary, a copy constructor and assignment operator that take a reference to the contents of the other dictionary, as well as the following methods: .. cpp:function:: uint32_t KL::Dict::size() const Returns the size (length) of the array. .. cpp:function:: bool KL::Dict::has( KeyTy const &key ) Returns ``true`` if and only if there is a value for the given key in the dictionary. .. cpp:function:: ValueTy const &KL::Dict::operator[]( KeyTy const &key ) const The read-only dictionary indexing operator. If there is no value for the given key in the dictionary an exception is thrown. .. cpp:function:: ValueTy const *KL::Dict::maybeGet( KeyTy const &key ) Get a pointer to the value corresponding to the given key. If there is no value for the given key, this method returns ``0``. .. cpp:function:: ValueTy &KL::Dict::operator[]( KeyTy const &key ) The read-write array indexing operator. It returns a mutable (read-write) reference to the value for the key in the dictionary. If there is no value for the key, a new value is created for the key. The initial value of the new value is the default value for :samp:`ValueTy`. .. cpp:function:: ValueTy &KL::Dict::get( KeyTy const &key, ValueTy const &defaultValue ) Get the value for the given key from the dictionary, returning an mutable (read-write) reference to the value. If there is no value for the key, a new value is created whose value is ``defaultValue``. .. note:: References returned from the array indexing operators should be considered temporary and should not be stored in other variables. Methods that potential modify the dictionary can cause the references to become invalid, leading to programming errors. .. cpp:function:: KL::Dict::iterator KL::Dict::begin() KL::Dict::iterator KL::Dict::end() KL::Dict::const_iterator KL::Dict::begin() const KL::Dict::const_iterator KL::Dict::end() const The iteration interface for dictionaries. Please refer to the :file:`EDKDicts.cpp` example in the :file:`$FABRIC_DIR/Samples/EDK/EDKDicts` folder for an example of dictionary iteration in the EDK. :code:`KL::Object` ^^^^^^^^^^^^^^^^^^ The :code:`KL::Object` type is the equivalent of the KL :code:`Object` type that refers to an arbitrary object. It supports an empty constructor (which constructs a null object reference), a copy constructor and an assignment operator (taking a reference to the other object) as well as the ``==`` and ``!=`` comparison operators. .. _types.user-defined: User-Defined Types ------------------ The KL :code:`struct`, :code:`interface` and :code:`object` types are user-defined types. They may be defined by the KL source files of the extension or one of the other extensions that the extension requires. User-defined types have C++ equivalents defined for them in the header generated by the :command:`kl2edk` tool. The following section detail usage of these C++ equivalent types. .. _EAG.types.structs: Structures ^^^^^^^^^^ KL structures (defined using the KL :code:`struct` keyword) are be directly represented by C++ structures. Each member of the KL structure is provided as a structure member in C++ with exactly the corresponding C++ type. You can therefore reference the members of an instance of the structure using the usual :code:`.` operation, as well as performing all the other usual C++ structure operations. Mapping KL Structures to Third-Party API Structures """""""""""""""""""""""""""""""""""""""""""""""""""""""" Since the generated C++ KL structure maps directly to a plain C++ structure with the KL types for its members, it is possible to pointer-cast the KL structure to another structure using the :code:`reinterpret_cast` operator in C++. However, you must ensure the following about the target structure: - The structure must only contain simple KL types or other structures containing simple KL types. For a list of C++ types equivalent to the simple KL types, see :ref:`types.simple.equivalent`. - The order of the members in the structure must be exactly the same in KL and in C++ - The structure must use the default C++ alignment for the structure and its members. .. _EAG.types.interfaces: Interfaces ^^^^^^^^^^ For each interface defined in the KL code there will be a C++ equivalent with the same name defined in the generated header. In the C++ class generated for the interface the methods of the interface are provided through the :samp:`{interface}.{methodName}({arg}, {arg}, ...)` call. Additionally, the C++ class provides: - An empty constructor that constructs a null interface reference - A copy constructor and an assignment operator that copy a reference to the other interface - The ``==`` and ``!=`` comparison operators that compare for interfaces to point to the same object - A conversion to the C++ type :code:`bool` as well as the :code:`operator !` that can be used for checks for the interface reference being non-null or null For example: .. code-block:: kl // KL code interface MyInt { Float32 foo(); }; function callIntMethod(MyInt myInt) = "CallIntMethod"; then the corresponding C++ definition for :code:`CallIntMethod` should be: .. code-block:: c++ // C++ code FABRIC_EXT_EXPORT void CallIntMethod( Fabric::EDK::KL::myInt::INParam myInt ) { Fabric::EDK::KL::Float32 result = myInt.foo(); Fabric::EDK::report("myInt.foo() returned %f", result); } .. _EAG.types.objects: Objects ^^^^^^^^^^ For each object defined in the KL code there will be a C++ equivalent with the same name defined in the generated header. The members of the object are accessed through the :samp:`{object}->{memberName}` operation. All of the members of the KL structure are provided through this operation. The methods of the object that belong to an interface that the object implements are provided through the :samp:`{object}.{methodName}({arg}, {arg}, ...)` call. .. note:: There is currently no way to call methods on the object that are not part of an implemented interface. - An empty constructor that constructs a null object reference - A static method :samp:`{objectType}\:\:Create()` constructs a new Object of type :samp:`objectType` and returns a reference to it - A copy constructor and an assignment operator that copy a reference to the other object - The ``==`` and ``!=`` comparison operators that compare for objects to point to the same object - A conversion to the C++ type :code:`bool` as well as the :code:`operator !` that can be used for checks for the object reference being non-null or null For example: .. code-block:: kl // KL code interface MyInt { Float32 foo(); }; object MyObj : MyInt { Byte b; String s; }; function displayObjectMembers(MyObj myObj) = "DisplayObjectMembers"; then the corresponding C++ definition for :code:`DisplayObjectMembers` should be: .. code-block:: c++ // C++ code FABRIC_EXT_EXPORT void DisplayObjectMembers( Fabric::EDK::KL::MyObj::INParam myObj ) { Fabric::EDK::report( "myObj.b=%u myObj.s=%s", unsigned(myObj->b), myObj->s.c_str() ); Fabric::EDK::KL::Float32 result = myObj.foo(); Fabric::EDK::report("myObj.foo() returned %f", result); } Refer to the EDKObjects sample located in ``$FABRIC_DIR/Samples/EDK/EDKObjects`` for a detailed example of exposing object functionality using the EDK.