|
c++和Unlua的交互
1. 背景2. 基本思路
2.1 (GlobalTable函数的交互)在c++定义暴露给UnLua的静态函数
2.1.1 该函数的基本需求:2.1.2 该函数的基本实现思路
2.2 (FLuaTable的交互)在c++定义暴露给UnLua的静态函数
2.2.1 该函数的基本需求2.2.2 该函数的实现思路
3. 完整的c++代码4. 注意
1. 背景
- 我们希望频繁变动的脚本是通过lua来完成的,因此我们引入了tx的UnLua(开源库)
- 我们会在c++中完成socket层面的处理,然后过滤出proto的字节流,这个字节流会从
- c++传递给lua,然后在lua中完成proto消息的处理
复制代码 2. 基本思路
- 1. 定义c++的静态函数
- 2. 在lua中访问该静态函数
复制代码 2.1 (GlobalTable函数的交互)在c++定义暴露给UnLua的静态函数
- UFUNCTION(BlueprintCallable, meta =(DisplayName ="CallLuaByGlobalTable", Category ="UnLua Tutorial"))staticvoidCallLuaByGlobalTable();
复制代码
然后我们就可以在lua中调用该c++的函数了
在这里需要进修UnLua的入门教程
2.1.1 该函数的基本需求:
- 1. 我们在TestReceiveCpp.lua中定义了一个函数叫做:CallMe的函数
复制代码- function TestReceiveCpp.CallMe(a, b)
- local ret = a + b
- local msg = string.format("c++ call a = %f,b = %f,ans = %f", a, b, ret)
- Screen.Print(msg)return
复制代码- 2. 我们希望在c++中去调用这个CallMe函数
复制代码 2.1.2 该函数的基本实现思路
- 1. 拿到对应lua脚本的闭包,并用变量TRC保留该闭包的引用
复制代码- UnLua::FLuaEnv Env;constauto bSuccess = Env.DoString("TRC = require 'TestReceiveCpp'");check(bSuccess);
复制代码- 显然,到这里,我们其实就是将定义的TestReceiveCpp的lua脚本加载到当前Env的内存当中
复制代码
- constauto RetValues = UnLua::CallTableFunc(Env.GetMainState(),"TRC","CallMe",1.1f,2.2f);check(RetValues.Num()==1);
复制代码- void AClient::CallLuaByGlobalTable(){
- UnLua::FLuaEnv Env;constauto bSuccess = Env.DoString("TRC = require 'TestReceiveCpp'");check(bSuccess);constauto RetValues = UnLua::CallTableFunc(Env.GetMainState(),"TRC","CallMe",1.1f,2.2f);check(RetValues.Num()==1);}
复制代码 2.2 (FLuaTable的交互)在c++定义暴露给UnLua的静态函数
2.2.1 该函数的基本需求
见2.1.1
2.2.2 该函数的实现思路
- 1. 利用UnLua自带的FLuaFuntion去加载require函数
复制代码- constauto Require = UnLua::FLuaFunction(&Env,"_G","require");
复制代码- 2. 利用requre函数获取TestReceiveCpp的闭包(加载到内存并返回引用)
复制代码- constauto RetValues1 = Require.Call("TestReceiveCpp");check(RetValues1.Num()==2);
复制代码- constauto RetValue = RetValues1[0];constauto LuaTable = UnLua::FLuaTable(&Env, RetValue);
复制代码- constauto RetValues2 = LuaTable.Call("CallMe",3.3f,4.4f);check(RetValues2.Num()==1);
复制代码- constauto Msg = FString::Printf(TEXT("[C++]收到来自Lua的返回,结果=%f"), RetValues2[0].Value<float>());PrintScreen(Msg);
复制代码 3. 完整的c++代码
.h- // Fill out your copyright notice in the Description page of Project Settings.#pragmaonce#include"CoreMinimal.h"#include"GameFramework/Actor.h"#include"Client.generated.h"UCLASS()
- class LUAX_API AClient : public AActor
- {GENERATED_BODY()
-
- public:// Sets default values for this actor's propertiesAClient();
- protected:// Called when the game starts or when spawned
- virtual voidBeginPlay() override;
- public:// Called every frame
- virtual voidTick(float DeltaTime) override;UFUNCTION(BlueprintCallable, meta =(DisplayName ="CallLuaByGlobalTable",
- Category ="UnLua Tutorial"))staticvoidCallLuaByGlobalTable();UFUNCTION(BlueprintCallable, meta =(DisplayName ="CallLuaByFLuaTable", Category ="UnLua Tutorial"))staticvoidCallLuaByFLuaTable();UFUNCTION(BlueprintCallable, meta =(DisplayName ="SetupCustomLoader", Category ="UnLua Tutorial"))staticvoidSetupCustomLoader(int Index);UFUNCTION(BlueprintNativeEvent, Category ="Switch Functions")voidOnReceiveMsg(float val);voidOnReceiveMsg_Implementation(float val);};
复制代码 .cpp- // Fill out your copyright notice in the Description page of Project Settings.#include"Client.h"#include"UnLua.h"#include"Kismet/KismetSystemLibrary.h"//#include "UnLua/"//#include "UnLua/"// Sets default values
- AClient::AClient(){// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
- PrimaryActorTick.bCanEverTick = true;}// Called when the game starts or when spawned// Called every framevoid AClient::Tick(float DeltaTime){
- Super::Tick(DeltaTime);OnReceiveMsg(DeltaTime);}void AClient::OnReceiveMsg_Implementation(float val){}staticvoidPrintScreen(const FString& Msg){
- UKismetSystemLibrary::PrintString(nullptr, Msg, true, false,FLinearColor(0,0.66,1),100);}void AClient::CallLuaByGlobalTable(){
- UnLua::FLuaEnv Env;constauto bSuccess = Env.DoString("TRC = require 'TestReceiveCpp'");check(bSuccess);constauto RetValues = UnLua::CallTableFunc(Env.GetMainState(),"TRC","CallMe",1.1f,2.2f);check(RetValues.Num()==1);}void AClient::CallLuaByFLuaTable(){PrintScreen(TEXT("[C++]CallLuaByFLuaTable 开始"));
- UnLua::FLuaEnv Env;constauto Require = UnLua::FLuaFunction(&Env,"_G","require");constauto RetValues1 = Require.Call("TestReceiveCpp");check(RetValues1.Num()==2);constauto RetValue = RetValues1[0];constauto LuaTable = UnLua::FLuaTable(&Env, RetValue);constauto RetValues2 = LuaTable.Call("CallMe",3.3f,4.4f);check(RetValues2.Num()==1);constauto Msg = FString::Printf(TEXT("[C++]收到来自Lua的返回,结果=%f"), RetValues2[0].Value<float>());PrintScreen(Msg);PrintScreen(TEXT("[C++]CallLuaByFLuaTable 结束"));}
- bool CustomLoader1(UnLua::FLuaEnv& Env,const FString& RelativePath, TArray<uint8>& Data, FString& FullPath){constauto SlashedRelativePath = RelativePath.Replace(TEXT("."),TEXT("/"));
- FullPath = FString::Printf(TEXT("%s%s.lua"),*GLuaSrcFullPath,*SlashedRelativePath);if(FFileHelper::LoadFileToArray(Data,*FullPath, FILEREAD_Silent))return true;
- FullPath.ReplaceInline(TEXT(".lua"),TEXT("/Index.lua"));if(FFileHelper::LoadFileToArray(Data,*FullPath, FILEREAD_Silent))return true;return false;}
- bool CustomLoader2(UnLua::FLuaEnv& Env,const FString& RelativePath, TArray<uint8>& Data, FString& FullPath){constauto SlashedRelativePath = RelativePath.Replace(TEXT("."),TEXT("/"));constauto L = Env.GetMainState();lua_getglobal(L,"package");lua_getfield(L,-1,"path");constchar* Path =lua_tostring(L,-1);lua_pop(L,2);if(!Path)return false;
- TArray<FString> Parts;FString(Path).ParseIntoArray(Parts,TEXT(";"), false);for(auto& Part : Parts){
- Part.ReplaceInline(TEXT("?"),*SlashedRelativePath);
- FPaths::CollapseRelativeDirectories(Part);if(FPaths::IsRelative(Part))
- FullPath = FPaths::ConvertRelativePathToFull(GLuaSrcFullPath, Part);else
- FullPath = Part;if(FFileHelper::LoadFileToArray(Data,*FullPath, FILEREAD_Silent))return true;}return false;}void AClient::SetupCustomLoader(int Index){switch(Index){case0:
- FUnLuaDelegates::CustomLoadLuaFile.Unbind();break;case1:
- FUnLuaDelegates::CustomLoadLuaFile.BindStatic(CustomLoader1);break;case2:
- FUnLuaDelegates::CustomLoadLuaFile.BindStatic(CustomLoader2);break;}}void AClient::BeginPlay(){
- Super::BeginPlay();SetupCustomLoader(1);}
复制代码 4. 注意
4.1 添加Lua的搜索路径
- bool CustomLoader1(UnLua::FLuaEnv& Env,const FString& RelativePath, TArray<uint8>& Data, FString& FullPath){constauto SlashedRelativePath = RelativePath.Replace(TEXT("."),TEXT("/"));
- FullPath = FString::Printf(TEXT("%s%s.lua"),*GLuaSrcFullPath,*SlashedRelativePath);if(FFileHelper::LoadFileToArray(Data,*FullPath, FILEREAD_Silent))return true;
- FullPath.ReplaceInline(TEXT(".lua"),TEXT("/Index.lua"));if(FFileHelper::LoadFileToArray(Data,*FullPath, FILEREAD_Silent))return true;return false;}
复制代码 4.2 缺少Lua库
如果报以下错误:
这是因为缺少Lua库
可以在.Build.cs中
添加
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|