公開関数の呼び出し規約(Calling Convention for Exported Functions)¶
警告
The use of the kl2edk tool to generate the header file with the types and function prototypes corresponding to KL code has mostly made this section irrelevant, since you can now guarantee that you use the right calling convention for your extension functions by just copying the function prototypes from the generated header file. However, we retain this section for reference and to help those looking for a deeper understanding of how KL interfaces with C++.
We saw in the サンプルエクステンションの解説 section that to return a string from a function exported to KL it was necessary to declare the C++ function signature with the return value as a first parameter and with the C++ function returning void
. In KL the function declaration was:
function String GetHelloWorldString() = "GetHelloWorldString";
whereas the function definition in C++ was:
FABRIC_EXT_EXPORT void GetHelloWorldString(
Fabric::EDK::KL::String &result
)
{
// ...
}
In order to have the extension function called correctly from KL it is necessary in some cases to adjust the C++ function parameters and return type. We refer to this as the calling convention for exported functions.
The rules for the calling convention are dependent on the types of the function parameters and the return type. For the purpose of the calling convention, there are two kinds of types: simple types and complex types.
Calling Convention for Simple Types¶
The simple types are the small, predefined types; they are:
Boolean
;- The integer types:
UInt8
,SInt8
,UInt16
,SInt16
,UInt32
,SInt32
,UInt64
andSInt64
; - The floating-point types:
Float32
andFloat64
; and - The aliases for simple types:
Integer
,Byte
,Index
,Size
andScalar
.
See Simple Types for more information about the simple types.
Simple types are directly returned from C++ functions and are directly passed by value as in
parameters:
- When a KL function returns a simple type the corresponding C++ function should also return the same simple type.
- When a KL function takes a simple type as an
in
parameter the C++ function should also take the same simple type by value. - When a KL function takes a simple type as an
io
parameter the C++ function should take the same simple type by reference.
For example, the KL function:
// KL code
function Boolean SimpleTypeFunc(
UInt32 inParam,
io Float32 ioParam
) = "SimpleTypeFuncImpl";
should have the C++ definition:
// C++ code
FABRIC_EXT_EXPORT Fabric::EDK::KL::Boolean SimpleTypeFuncImpl(
Fabric::EDK::KL::UInt32 inParam,
Fabric::EDK::KL::Float32 &ioParam
)
{
// ...
return true; // directly return value
}
Calling Convention for Complex Types¶
The complex types are all the types that are not simple types. They include:
- KL::String
- All container types; see KL::VariableArray<Ty>
- All user-defined types; see User-Defined Types
Complex types are always passed by reference. Furthermore, in the case they are returned from functions the return value should be stored into a hidden first reference parameter; the resulting function should return void. In order to simplify the use of this convention, the typedefs INParam
, IOParam
and RetVal
are provided for each built-in complex type; see
In order to facilitate this, predefined complex types provide typedefs that help with this calling convention:
KL::<ComplexType>::INParam
The type of anin
parameter from KL.
KL::<ComplexType>::IOParam
The type of anio
parameter from KL.
KL::<ComplexType>::Result
The type of a “hidden return parameter” in KL.
注釈
A hidden return parameter must always be the first parameter of the C++ function in which it is used. This condition cannot be enforced by the
FabricEDK.h
header, therefore it is the programmer’s responsibility to ensure it is met.
If you wish to provide these same typedefs in your custom structure definitions, use the FABRIC_EDK_COMPLEX_TYPE(TypeName)
macro as demonstrated below.
For example, the following KL function declaration:
struct MyType {
String st;
};
function String myFunc(
UInt32 uint32s[],
io String dict[UInt32],
MyType myType
) = "MyFunc";
should be represented by the following C++ function:
struct MyType
{
FABRIC_EDK_COMPLEX_TYPE(MyType)
KL::String st;
};
FABRIC_EDK_EXPORT void MyFunc(
KL::String::Result result, // hidden return parameter
KL::VariableArray<KL::UInt32>::INParam uint32s,
KL::Dict<KL::UInt32, KL::String>::IOParam dict,
MyType::INParam myType
)
{
// ...
}
Mixing Simple and Complex Types¶
It is perfectly acceptable (and common) to mix simple and complex types in extension functions; you must simply follow the rules for each type individually.