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 kl2edk as well as the 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 Fabric::EDK::KL namespace.

注釈

For brevity, all types in this section will be referred to without the Fabirc::EDK:: namespace prefix as if the using namespace Fabric::EDK; directive had been issued.

Simple Types

The simple types are all simply aliases for existing C++ types.

When a simple type is passed as an 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 Calling Convention for Simple Types 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 Data type. This is simply a type alias for void *; however, there is a KL::DataWrapper template provided by FabricEDK.h that makes it much easier to work with these pointers; see The KL::DataWrapper<Ty> and KL::ConstDataWrapper<Ty> Templates for more information.

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

The KL::DataWrapper<Ty> and KL::ConstDataWrapper<Ty> Templates

In order to simplify use of the KL::Data type, FabricEDK.h provides the templates KL::DataWrapper<Ty> KL::ConstDataWrapper<Ty> that allows you to treat a value of type KL::Data as if it were a pointer to a more complex type. KL::DataWrapper<Ty> allows modification of the resulting complex type whereas KL::ConstDataWrapper<Ty> allows it only to be read. The best explanation is through an example:

struct SomeMoreComplexStruct {
  InternalValue value;
  // ....
};

FABRIC_EDK_EXPORT void MyFunc( Fabric::EDK::KL::Data::IOParam data )
{
  Fabric::EDK::KL::DataWrapper<SomeMoreComplexStruct> complexStruct( data );

  if ( !complexStruct ) {
    // Note that this assignment actually changes the referenced
    complexStruct = new SomeMoreComplexStruct;
    complexStruct->value = // ... whatever
  }
}

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 kl2edk or the FabricEDK.h header file.

Complex types must always be passed by reference in C++ functions corresponding to KL functions, even when they are in parameters in KL; similarly, they must always be returned through a “hidden return parameter”. This is usually done using the ::INParam and ::Result typedefs. For more information, see Calling Convention for Complex Types.

警告

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.

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:

const char *KL::String::c_str() const

Returns the string contents as a C-style null-terminated string.

const char *KL::String::data() const

Returns the string contents as a raw pointer to character data.

uint32_t KL::String::length() const

Returns the string contents as a raw pointer to character data.

void KL::String::append(char ch)

Appends a character to the string.

void KL::String::operator+=(char ch)

Alias for void KL::String::append(char ch).

void KL::String::append(char const *data, uint32_t length)

Appends another string given as a raw character pointer and a length.

void KL::String::append(char const *cStr)

Appends another string given as a C-style null-terminate string.

void KL::String::operator+=(char const *cStr)

Alias for void KL::String::append(char const *cStr).

void KL::String::append(KL::String const &that)

Appends another KL::String.

void KL::String::operator+=(KL::String const &that)

Alias for void KL::String::append(KL::String const &that).

KL::VariableArray<Ty>

Provides the functionality of a variable array of the type 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:

template<>
uint32_t KL::VariableArray<Ty>::size() const

Returns the size (length) of the array.

template<>
void KL::VariableArray<Ty>::resize(uint32_t newSize)

Resize the array. The new elements (if any) will be initialized using the constructor for the given type.

template<>
void KL::VariableArray<Ty>::push_back(Ty const &t)

Append an element to the end of the array

template<>
Ty const &KL::VariableArray<Ty>::operator[](uint32_t index) const

The read-only array indexing operator.

template<>
Ty &KL::VariableArray<Ty>::operator[](uint32_t index)

The read-write array indexing operator. It returns a modifiable reference to the given element of the array.

注釈

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.

注釈

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.

KL::FixedArray<Ty, size>

Provides the functionality of a KL fixed array of the type 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:

template<>
Ty const &KL::ExternalArray<Ty>::operator[](uint32_t index) const

The read-only array indexing operator.

template<>
Ty &KL::ExternalArray<Ty>::operator[](uint32_t index)

The read-write array indexing operator. It returns a modifiable reference to the given element of the array.

KL::ExternalArray<Ty>

Provides the functionality of a external array of the type 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:

KL::ExternalArray<Ty> ExternalArray(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 Engine.

template<>
uint32_t KL::ExternalArray<Ty>::size() const

Returns the size (length) of the array.

template<>
Ty const &KL::ExternalArray<Ty>::operator[](uint32_t index) const

The read-only array indexing operator.

template<>
Ty &KL::ExternalArray<Ty>::operator[](uint32_t index)

The read-write array indexing operator. It returns a modifiable reference to the given element of the array.

警告

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.

KL::Dict<KeyTy, ValueTy>`

Provides the functionality of a dictionary that maps keys of type KeyTy to values of type ValueTy. KeyTy must be either a simple type or KL::String; 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:

template<>
uint32_t KL::Dict<KeyTy, ValueTy>::size() const

Returns the size (length) of the array.

template<>
bool KL::Dict<KeyTy, ValueTy>::has(KeyTy const &key)

Returns true if and only if there is a value for the given key in the dictionary.

template<>
ValueTy const &KL::Dict<KeyTy, ValueTy>::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.

template<>
ValueTy const *KL::Dict<KeyTy, ValueTy>::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.

template<>
ValueTy &KL::Dict<KeyTy, ValueTy>::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 ValueTy.

template<>
ValueTy &KL::Dict<KeyTy, ValueTy>::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.

注釈

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.

template<>
KL::Dict<KeyTy, ValueTy>::iterator KL::Dict<KeyTy, ValueTy>::begin()
template<>
KL::Dict<KeyTy, ValueTy>::iterator KL::Dict<KeyTy, ValueTy>::end()
template<>
KL::Dict<KeyTy, ValueTy>::const_iterator KL::Dict<KeyTy, ValueTy>::begin() const
template<>
KL::Dict<KeyTy, ValueTy>::const_iterator KL::Dict<KeyTy, ValueTy>::end() const

The iteration interface for dictionaries. Please refer to the EDKDicts.cpp example in the $FABRIC_DIR/Samples/EDK/EDKDicts folder for an example of dictionary iteration in the EDK.

KL::Object

The KL::Object type is the equivalent of the KL 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.

User-Defined Types

The KL struct, interface and 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 kl2edk tool. The following section detail usage of these C++ equivalent types.

Structures

KL structures (defined using the KL 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 . 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 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 Equivalences for Simple Types.
  • 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.

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 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 bool as well as the operator ! that can be used for checks for the interface reference being non-null or null

For example:

// KL code

interface MyInt {
  Float32 foo();
};

function callIntMethod(MyInt myInt) = "CallIntMethod";

then the corresponding C++ definition for CallIntMethod should be:

// 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);
}

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 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 object.methodName(arg, arg, ...) call.

注釈

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 objectType::Create() constructs a new Object of type 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 bool as well as the operator ! that can be used for checks for the object reference being non-null or null

For example:

// KL code

interface MyInt {
  Float32 foo();
};

object MyObj : MyInt {
  Byte b;
  String s;
};

function displayObjectMembers(MyObj myObj) = "DisplayObjectMembers";

then the corresponding C++ definition for DisplayObjectMembers should be:

// 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.