3.4. 公开 C++ 处理类型

处理类型表示旨在向 Daslang 公开 C++ 类型的机制。

处理类型是通过从 TypeAnnotation 派生自定义类型注释并将该注释的实例添加到所需的模块来创建的。例如:

template <typename VecT, int RowC>
class MatrixAnnotation : public TypeAnnotation {
...

typedef MatrixAnnotation<float4,4> float4x4_ann;

Module_Math() : Module("math") {
    ...
    addAnnotation(make_smart<float4x4_ann>());

3.4.1. TypeAnnotation

TypeAnnotation 包含一组用于描述类型属性的虚拟方法,以及用于实现特定功能的模拟节点的方法。

canAot 返回true,如果类型可以出现在 AOT:

virtual bool canAot(das_set<Structure *> &) const

canCopy, canMovecanClone 允许复制、移动或克隆类型:

virtual bool canMove() const
virtual bool canCopy() const
virtual bool canClone() const

isPodisRawPod 指定类型是 plain old data 还是 plain old data (不带指针的普通旧数据):

virtual bool isPod() const
virtual bool isRawPod() const

isRefType 指定类型 ABI,即它是通过引用还是按值传递:

virtual bool isRefType() const

isLocal 允许创建该类型的局部变量:

virtual bool isLocal() const

canNew, canDeletecanDeletePtr 指定是否允许对类型执行 NEW 和 DELETE作,以及是否可以删除指向该类型的指针:

virtual bool canNew() const
virtual bool canDelete() const
virtual bool canDeletePtr() const

needDelete 指定自动生成的终结器是否要删除此类型:

virtual bool needDelete() const

isIndexable 指定是否允许该类型的索引作 []

virtual bool isIndexable ( const TypeDeclPtr & ) const

isIterable 指定类型是否可以作为 for 循环的源:

virtual bool isIterable ( ) const

isShareable 指定是否可以将类型的全局变量标记为 shared:

virtual bool isShareable ( ) const

isSmart 指定指向该类型的指针是否显示为smart_ptr:

virtual bool isSmart() const

canSubstitute 查询该类型是否允许 LSP,即该类型可以向下转换:

virtual bool canSubstitute ( TypeAnnotation * /* passType */ ) const

getSmartAnnotationCloneFunction 返回 := 运算符替换的克隆函数名称:

virtual string getSmartAnnotationCloneFunction () const { return ""; }

getSizeOfgetAlignOf 分别返回类型的大小和对齐方式:

virtual size_t getSizeOf() const
virtual size_t getAlignOf() const

makeFieldType``makeSafeFieldType``返回指定字段的类型 (如果未找到该字段,则返回 null):

virtual TypeDeclPtr makeFieldType ( const string & ) const
virtual TypeDeclPtr makeSafeFieldType ( const string & ) const

makeIndexType 返回给定索引表达式的 [] 运算符的类型(如果不支持,则返回 null):

virtual TypeDeclPtr makeIndexType ( const ExpressionPtr & /*src*/, const ExpressionPtr & /*idx*/ ) const

makeIteratorType 返回用作 for 循环源时可迭代变量的类型(如果不支持,则返回 null):

virtual TypeDeclPtr makeIteratorType ( const ExpressionPtr & /*src*/ ) const

aotPreVisitGetField, aotPreVisitGetFieldPtr, aotVisitGetField, 和 aotVisitGetFieldPtr 为字段和指针字段取消引用生成特定的 AOT 前缀和后缀:

virtual void aotPreVisitGetField ( TextWriter &, const string & )
virtual void aotPreVisitGetFieldPtr ( TextWriter &, const string & )
virtual void aotVisitGetField ( TextWriter & ss, const string & fieldName )
virtual void aotVisitGetFieldPtr ( TextWriter & ss, const string & fieldName )

有许多 simulate... 例程为不同的场景提供特定的仿真节点:

virtual SimNode * simulateDelete ( Context &, const LineInfo &, SimNode *, uint32_t ) const
virtual SimNode * simulateDeletePtr ( Context &, const LineInfo &, SimNode *, uint32_t ) const
virtual SimNode * simulateCopy ( Context &, const LineInfo &, SimNode *, SimNode * ) const
virtual SimNode * simulateClone ( Context &, const LineInfo &, SimNode *, SimNode * ) const
virtual SimNode * simulateRef2Value ( Context &, const LineInfo &, SimNode * ) const
virtual SimNode * simulateGetNew ( Context &, const LineInfo & ) const
virtual SimNode * simulateGetAt ( Context &, const LineInfo &, const TypeDeclPtr &,
                                 const ExpressionPtr &, const ExpressionPtr &, uint32_t ) const
virtual SimNode * simulateGetAtR2V ( Context &, const LineInfo &, const TypeDeclPtr &,
                                    const ExpressionPtr &, const ExpressionPtr &, uint32_t ) const
virtual SimNode * simulateGetIterator ( Context &, const LineInfo &, const ExpressionPtr & ) const

walk 提供自定义数据遍历功能,以允许对类型进行检查和二进制序列化:

virtual void walk ( DataWalker &, void * )

3.4.2. ManagedStructureAnnotation

ManagedStructureAnnotation 是一个帮助程序类型注释模板,旨在简化大多数 C++ 类的绑定。

让我们回顾一下以下示例:

struct Object {
    das::float3   pos;
    das::float3   vel;
    __forceinline float speed() { return sqrt(vel.x*vel.x + vel.y*vel.y + vel.z*vel.z); }
};

为了绑定它,我们从 ManagedStructureAnnotation 继承,提供一个名称,并注册字段和属性:

struct ObjectStructureTypeAnnotation : ManagedStructureAnnotation <Object> {
    ObjectStructureTypeAnnotation(ModuleLibrary & ml) : ManagedStructureAnnotation ("Object",ml) {
        ...

addFieldaddProperty 用于相应地添加字段和属性。 字段注册为 ref 值。 属性注册的偏移量为 -1,并按值返回:

ObjectStructureTypeAnnotation(ModuleLibrary & ml) : ManagedStructureAnnotation ("Object",ml) {
    addField<DAS_BIND_MANAGED_FIELD(pos)>("position","pos");
    addField<DAS_BIND_MANAGED_FIELD(vel)>("velocity","vel");
    addProperty<DAS_BIND_MANAGED_PROP(speed)>("speed","speed");

之后,我们注册一个类型工厂并向模块添加类型注释:

MAKE_TYPE_FACTORY(Object, Object)

addAnnotation(make_smart<ObjectStructureTypeAnnotation>(lib));

addFieldEx 允许注册自定义偏移量或类型:

addFieldEx ( "flags", "flags", offsetof(MakeFieldDecl, flags), makeMakeFieldDeclFlags() );

这样,一种类型的字段可以注册为另一种类型。

Managed structure annotation 会自动为公开的字段实现 walk

3.4.3. DummyTypeAnnotation

当某个类型需要暴露给 Daslang 时,会出现 DummyTypeAnnotation ,但不允许任何内容或作。

这样,该类型可以是其他结构的一部分,并传递给需要它的 C++ 函数。

虚拟类型注释构造函数采用 Daslang 类型名称、C++ 类型名称、其大小和对齐方式:

DummyTypeAnnotation(const string & name, const string & cppName, size_t sz, size_t al)

由于 TypeAnnotation 是一个强 Daslang 类型,DummyTypeAnnotation 允许在 Daslang 中 gluing 代码,而不暴露 C++ 类型的细节。 请考虑以下示例:

send_unit_to(get_unit(“Ally”), get_unit_pos(get_unit(“Enemy”)))

get_unit 的结果直接传递给 send_unit_to,而 Daslang 不知道任何关于单位类型的信息(除了它存在)。

3.4.4. ManagedVectorAnnotation

ManagedVectorAnnotation 用于将标准库向量公开给 Daslang。

在大多数情况下,不需要集成,并且 vector 注释会自动添加到模块中,这些模块会以任何形式注册与 vector 相关的任何内容。

向量与以下 4 个函数一起注册,类似于 Daslang 数组的函数:

push(vec, value)
pop(vec)
clear(vec)
resize(vec, newSize)

Vectors 还暴露了字段 length ,它返回 vector 的当前大小。

托管向量注释会自动实现 walk,类似于 Daslang 数组。

3.4.5. ManagedValueAnnotation

ManagedValueAnnotation 旨在公开 C++ POD 类型,这些类型按值传递。

它期望为该类型实现 cast 机制。