//структура с методами structMyStruct { inttest(){ return42; } };
//тип-обёртка, описание структуры для daScript structMyStructTypeAnnotation : ManagedStructureAnnotation <MyStruct> { MyStructTypeAnnotation(ModuleLibrary& ml) : ManagedStructureAnnotation("MyStruct", ml) { //тут может быть описание полей } }; MAKE_TYPE_FACTORY(MyStruct, MyStruct)
//описание модуля classModule_Tutorial02 :public Module { public: Module_Tutorial02() : Module("tutorial_02") { // module name, when used from das file ModuleLibrary lib; lib.addModule(this); lib.addBuiltInModule();
//описание структуры addAnnotation(make_smart<MyStructTypeAnnotation>(lib));
//регистрация метода using method_test = DAS_CALL_MEMBER(MyStruct::test); addExtern<DAS_CALL_METHOD(method_test)>(*this, lib, "mystruct_test", SideEffects::none, DAS_CALL_MEMBER_CPP(MyStruct::test)); } };
//возможный вызов метода в daScript
var c: MyStruct
print("{c|> mystruct_test()}")
Привязка перегруженных и шаблонных функций с явным указанием сигнатуры
inttest2(int a){ return a; }
template <typename T> T test3(T a){ return a; }
//явное указание сигнатуры функции для привязки addExtern<int(*)(int),test2>(*this, lib, "test2", SideEffects::none, "test2"); addExtern<int(*)(int), test3>(*this, lib, "test3", SideEffects::none, "test3");
//returns a ref type by value, addExtern<DAS_BIND_FUN(float4x4_translation), SimNode_ExtFuncCallAndCopyOrMove>(*this, lib, "translation", SideEffects::none, "float4x4_translation")->arg("xyz");
Привязка других типов нод AST Способы привязать семантику вызова функции на стороне daScript к генерации других типов нод
Создание своего типа-хендла, который в dascript будет обрабатываться как примитивный тип uint64
structMyHandle { uint64_t id; //другие методы и свойства handle }; MAKE_TYPE_FACTORY(MyHandle, MyHandle)
//описываем методы каста к примитивному типу и обратно namespace das { template <> structcast<MyHandle> { static __forceinline MyHandle to(vec4f x){ return MyHandle{ (uint64_t)v_extract_xi64(v_cast_vec4i(x)) }; } static __forceinline vec4f from(MyHandle x){ return v_cast_vec4f(v_splatsi64(x.id)); } }; }
//описываем аннотацию типа с перегруженным методом walk structMyHandleAnnotationfinal : ManagedStructureAnnotation<MyHandle> { public: MyHandleAnnotation(ModuleLibrary& ml) : ManagedStructureAnnotation("MyHandle", ml) {}
boolhasNonTrivialCtor()constoverride{ returnfalse; } //trivial type boolcanClone()constoverride{ returntrue; }
virtualvoidwalk(DataWalker& walker, void* data)override { if (!walker.reading) { const MyHandle* t = (MyHandle*)data; uint64_t eidV = t->id; walker.UInt64(eidV); } }
Симуляция итератора Для кастомного контейнера можно задать прямой способ обращения к элементам (для простоты — нешаблонная версия кода)
//кастомный вектор из элементов MyHandle structMyVector { std::vector<MyHandle> vec; }; MAKE_TYPE_FACTORY(MyVector, MyVector)
//создаём вектор в C++ и делаем функцию доступа к нему из daScript MyVector gVector = { {MyHandle{1}, MyHandle{3}, MyHandle{5}} }; auto& getArrayRef(){ return gVector; }
virtualboolfirst(das::Context&, char* _value)override { if (!array->vec.size()) returnfalse; iterator_type* value = (iterator_type*)_value; *value = array->vec.begin(); //пишем в память, выделенную в daScript под итератор end = array->vec.end(); returntrue; }
virtualboolnext(das::Context&, char* _value)override { iterator_type* value = (iterator_type*)_value; ++(*value); //сдвигаем курсор на следующий элемент return *value != end; }
virtualvoidclose(das::Context& context, char* _value)override { //освобождаем итератор, по хорошему нужно еще занулить value context.heap->free((char*)this, sizeof(MyIterator)); }
//в аннотации типа вектора говорим: //"при обращении к итератору контейнера из daScript будет создан кастомный класс итератора и вызываться его методы" structMyVectorAnnotationfinal : ManagedStructureAnnotation<MyVector, false> { protected: TypeDeclPtr vecType; public: