找回密码
 立即注册
查看: 392|回复: 0

UE4学习之路3:Puerts用ts调用C++

[复制链接]
发表于 2023-8-15 15:45 | 显示全部楼层 |阅读模式
简介:

       ts怎么调用ue4中的类呢?
       首先,puerts已经辅佐我们生成了大部门的类:是指UCLASS,USTRUCT标识表记标帜UPPROPERTY,UFUNCTION的属性、方式,可以直接在ts中包含库ue,就能使用对应类提供的方式。其他类想使用怎么去措置呢。
       比如我们可能使用某些第三方库只有C++版本,那么关于第三方库怎么在ts脚本中调用呢?比如网络库,我们在ts脚本经常会调用发送网络动静函数,必需颠末c++调用第三方库来发出去。
       或者我们本身写了一个担任ue4的某个子类,但愿可以被ts访谒到。
1. 普通C++类:

       首先感激大佬的无私付出,才能使用Puerts,贴出大佬的文章:
https://github.com/Tencent/puerts/blob/master/doc/unreal/template_binding.md
       说下工程的具体法式:
       首先还是之前的项目,我们在Source/InstallPuerts的目录下,创建两个文件:Calc.h 和Calc.cpp文件。创建成功后,添加如下代码:
  1. // .h 文件
  2. #pragma once
  3. class CalA
  4. {
  5. public:
  6.         static int32_t Add(int32_t a, int32_t b)
  7.         {
  8.                 return a + b;
  9.         }
  10.         int32_t Get()
  11.         {
  12.                 return m_c;
  13.         }
  14.         int m_c;
  15. private:
  16.         int m_d;
  17. };
  18. class CalB
  19. {
  20. public:
  21.         static int32_t Add(int32_t a, int32_t b)
  22.         {
  23.                 return a + b;
  24.         }
  25. private:
  26. };
  27.       
  28. // .cpp文件
  29. #include ”Calc.h”
  30. #include ”Binding.hpp”
  31. UsingCppType(CalA);
  32. UsingCppType(CalB);
  33. struct AutoRegisterForCalAB
  34. {
  35.     AutoRegisterForCalAB()
  36.     {
  37.         puerts::DefineClass<CalA>().Function(”AddA”, MakeFunction(&CalA::Add)).Register();
  38.         puerts::DefineClass<CalB>().Function(”AddF”, MakeFunction(&CalB::Add)).Register();
  39.     }
  40. };
  41. AutoRegisterForCalAB _AutoRegisterForCalAB__;
复制代码
         这两个类的声明相信大师都看得懂,主要在cpp文件,首先要包含生成ts的代码的头文件,然后固定格式,使用UsingCppType是在声明要生成ts。然后主要代码是
        puerts::DefineClass<类名>().Functiong(”生成的ts的函数名”,使用的函数).Register();
        AutoRegisterForCalAB这个布局体可有可无,其实就是通过布局体的自动创建过程来达到调用函数的目的。这两个函数也可以放到其他启动的函数处所。
        加完之后,打开UE4项目工程,还是之前我们创建的工程。点击编译,完成后再点击ue.d.ts按钮,在目录Plugins/Puerts/Typing/cpp中,就生成了文件index.d.ts:
  1. declare module ”cpp” {
  2.     import * as UE from ”ue”
  3.     import {$Ref, $Nullable} from ”puerts”
  4.     class CalA {
  5.         static AddA(p0: number, p1: number) :number;
  6.     }
  7.     class CalB {
  8.         static AddF(p0: number, p1: number) :number;
  9.     }
  10. }      
复制代码
         但愿大师都按照流程生成了这个文件。
          如何使用呢,就正常引用cpp文件,调用就好了。
  1. import * as UE from &#39;ue&#39;
  2. import {$ref, $unref, $set, argv, on, toManualReleaseDelegate, releaseManualReleaseDelegate} from &#39;puerts&#39;;
  3. import * as cpp from &#39;cpp&#39;
  4. console.log(”Quick start ---------------aaaaaaaaaaaaa----------------”);
  5. let Cala = cpp.CalA;
  6. console.log(Cala.AddA(12, 34));
复制代码
       UE4中运行:查看控制台:


       成功输出成果46。
       有个处所需要注意:就是在执行ue.d.ts生成ts代码的时候,如果是新增类,或者改削类的名字等,可以生成正确的ts文件,如果是删掉某个方式,则会漏掉删除操作,且封锁ue4的时候会报出ue4崩溃的问题,解决方式是封锁ue4改削可以达到效果。这个我咨询了puerts的创建者车大佬,感激大佬的回答,应该是ue4的live reload的功能不完善,不是puerts的问题
重头戏:说下方式或者属性如何转化:以后使用法式员基础技能:复制粘贴模板。
  1. // Binging.hpp 文件内定义
  2. //
  3. // 撑持注册的方式
  4. ClassDefineBuilder<T>& Constructor(InitializeFuncType constructor, int length, const CFunctionInfo** infos);
  5. ClassDefineBuilder<T>& Function(const char* name, FunctionCallbackType func, const CFunctionInfo* info);
  6. ClassDefineBuilder<T>& Function(const char* name, FunctionCallbackType func, int length, const CFunctionInfo** infos)
  7. ClassDefineBuilder<T>& Method(const char* name, FunctionCallbackType func, const CFunctionInfo* info);
  8. ClassDefineBuilder<T>& Method(const char* name, FunctionCallbackType func, int length, const CFunctionInfo** infos)
  9. ClassDefineBuilder<T>& Property(const char* name, FunctionCallbackType getter, FunctionCallbackType setter = nullptr, const char* type = nullptr)
  10. // 生成特定参数的方式
  11. #define MakeConstructor(T, ...) ::puerts::template ConstructorWrapper<T, ##__VA_ARGS__>
  12. #define MakeGetter(M) &(::puerts::PropertyWrapper<decltype(M), M>::getter)
  13. #define MakeSetter(M) &(::puerts::PropertyWrapper<decltype(M), M>::setter)
  14. #define MakeProperty(M) &(::puerts::PropertyWrapper<decltype(M), M>::getter), &(::puerts::PropertyWrapper<decltype(M), M>::setter), ::puerts::PropertyWrapper<decltype(M), M>::info()
  15. #define MakeFunction(M) &(::puerts::FuncCallWrapper<decltype(M), M>::call), ::puerts::FuncCallWrapper<decltype(M), M>::info()
  16. #define SelectFunction(SIGNATURE, M) &(::puerts::FuncCallWrapper<SIGNATURE, M>::call), ::puerts::FuncCallWrapper<SIGNATURE, M>::info()
  17. #define MakeCheckFunction(M) &(::puerts::FuncCallWrapper<decltype(M), M>::checkedCall), ::puerts::FuncCallWrapper<decltype(M), M>::info()
  18. #define MakeOverload(SIGNATURE, M) puerts::FuncCallWrapper<SIGNATURE, M>
  19. #define CombineOverloads(...) &::puerts::OverloadsCombiner<__VA_ARGS__>::call, ::puerts::OverloadsCombiner<__VA_ARGS__>::length, ::puerts::OverloadsCombiner<__VA_ARGS__>::infos()
  20. #define CombineConstructors(...) &::puerts::ConstructorsCombiner<__VA_ARGS__>::call, ::puerts::ConstructorsCombiner<__VA_ARGS__>::length, ::puerts::ConstructorsCombiner<__VA_ARGS__>::infos()
  21. // 怎么使用:
  22. // 构造函数:  仅有一个int参数的构造函数
  23. puerts::DefineClass<CalA>()
  24.     .Constructor<int>()
  25.     .Register();
  26. // 构造函数:  多个构造函数
  27. puerts::DefineClass<CalA>()
  28.     .Constructor(CombineConstructors(
  29.         MakeConstructor(CalA, int32_t, int32_t),
  30.         MakeConstructor(CalA)
  31.         ))
  32.     .Register();
  33. // 静态函数:  单一函数
  34. puerts::DefineClass<CalA>()
  35.     .Function(”Add”, MakeFunction(&CalA::Add))
  36.     .Register();
  37. // 静态函数:  多个重载函数,假设CalA有4个构造函数,参数分袂是下面4种
  38. puerts::DefineClass<CalA>()
  39.     .Function(”Overload”, CombineOverloads(
  40.         MakeOverload(void(*)(), &CalA::Overload),
  41.         MakeOverload(void(*)(int32_t), &CalA::Overload),
  42.         MakeOverload(void(*)(int32_t, int32_t), &CalA::Overload),
  43.         MakeOverload(void(*)(std::string, int32_t), &CalA::Overload)
  44.     ))
  45.     .Register();
  46. // 成员函数:   无重载
  47. puerts::DefineClass<CalA>()
  48.     .Method(”Add”, MakeFunction(&CalA::Add))
  49.     .Register();
  50. // 成员函数:   多个重载,以及连着写法
  51. puerts::DefineClass<CalA>()
  52.     .Method(”OverloadMethod”, CombineOverloads(
  53.         MakeOverload(int32_t(CalA::*)(), &CalA::OverloadMethod),
  54.         MakeOverload(int32_t(CalA::*)(int32_t), &CalA::OverloadMethod),
  55.         MakeOverload(uint32_t(CalA::*)(uint32_t), &CalA::OverloadMethod),
  56.         MakeOverload(int64_t(CalA::*)(int64_t), &CalA::OverloadMethod)
  57.         ))
  58.     .Method(”GetSelf”, MakeFunction(&CalA::GetSelf))
  59.     .Register();
  60. // 成员变量:  
  61. puerts::DefineClass<TestClass>()
  62.     .Property(”X”, MakeProperty(&TestClass::X))
  63.     .Property(”Y”, MakeProperty(&TestClass::Y))
  64.     .Register();
复制代码
2. UE4的类:


         本身编写的担任UE4的类,也必需在文件Source/XXX项目路径下,否则是没法子生成ts的,不外有些东西没必要生成ts的类,也别放在这个目录下,否则会生成ts代码。
       担任的UE的类,声明为UFUNCTION和UPROPERTY的,不需要额外写注册的代码,只需ue4编译并点击ue.d.ts,就能生成ts代码,生成路径是:Plugins\Puerts\Typing\ue目录。
      比如我写的:
就能引用到了:
  1. // .h文件
  2. #pragma once
  3. #include ”ArrayBuffer.h”
  4. #include ”CoreMinimal.h”
  5. #include ”UObject/NoExportTypes.h”
  6. #include ”TestObject.generated.h”
  7. /**
  8. *
  9. */
  10. UCLASS()
  11. class INSTALLPUERTS_API UMyTestObject : public UObject
  12. {
  13.     GENERATED_BODY()
  14. public:
  15.     UMyTestObject();
  16.     UFUNCTION(BlueprintCallable, meta = (DisplayName = ”Add”, ScriptName = ”Add”, Keywords = ”test”), Category = ”Test”)
  17.         int32 Add(int32 a, int32 b) const;
  18.     ~UMyTestObject();
  19. };
  20. // .cpp文件
  21. #include ”TestObject.h”
  22. UMyTestObject::UMyTestObject()
  23. {
  24. }
  25. UMyTestObject::~UMyTestObject()
  26. {
  27. }
  28. int32 UMyTestObject::Add(int32 a, int32 b) const
  29. {
  30.         return a+b;
  31. }
复制代码
ts文件包含库ue就能访谒了。
下面说说非UFUNTION,和UPROPERTY怎么生成:
比如UObject的GetName,GetWorld不是UFUNCTION
  1. #include ”CoreMinimal.h”
  2. #include ”Binding.hpp”
  3. #include ”UEDataBinding.hpp”
  4. UsingUClass(UObject)
  5. UsingUClass(UWorld) // for return type
  6. puerts::DefineClass<UObject>()
  7.     .Method(”GetName”, SelectFunction(FString (UObjectBaseUtility::*)() const, &UObjectBaseUtility::GetName))
  8.     .Method(”GetWorld”, MakeFunction(&UObject::GetWorld))
  9.     .Register();
复制代码
这里因为是UE的类,所以不能使用UsingCppType,要使用UsingUClass,后面的函数基本一样。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-22 22:06 , Processed in 0.102596 second(s), 27 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表