集成平行云 数据通道 C++ sdk 到UE4

2022-07-25,,,,

1新建c++ 项目  (我用的是4.25.4版本的引擎)

2新建第三方库插件

3不着急 关掉UE4界面,在Browser窗口空白地方右键,创建c++类

4经过综合考虑,还是Component组件比较合适

5记得要选插件的Runtime

6如果出现报错不要怕,正常显现,此时关闭UE4工程,关闭VS

7打开D:\SVN_Local\MyProject\Plugins\PXYDataChannel\Source\ThirdParty\PXYDataChannelLibrary

删除以下文件并将平行云提供的SDK放到指定文件夹

          

             

8对着 “ MyProject.uproject”  文件右键,重新生成VS文件,并等待进度条走完

9重新打开VS工程,找到PXYDataChannelLibrary.Build.cs

10 修改PXYDataChannel.cpp 文件

11此时编译,报错

12 在 PXYDataChannel.Build.cs 文件的 PrivateDependencyModuleNames.AddRange 中添加依赖

"CoreUObject",
                "Engine",
                "Slate",
                "SlateCore",

再次编译,正常通过。

13 将c++  例子中的代码移植到UE4  component 组件中

PXYDataChannelComponent.h

include "LarkXRDataChannel.h"
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "PXYDataChannelComponent.generated.h"

static const char* P_Component_Data;

UENUM(BlueprintType)
enum class p_data_type : uint8
{
	DATA_STRING = 0,
	DATA_BIN = 1,
};

DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FMuitDynamicDelegate, p_data_type, type, FString, dataText);
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class UPXYDataChannelComponent : public UActorComponent
{
	GENERATED_BODY()

public:	
	// Sets default values for this component's properties
	UPXYDataChannelComponent();
	UPROPERTY(EditAnywhere, BlueprintReadWrite, BlueprintAssignable, Category = "Events|P")
		FMuitDynamicDelegate p_MuitDynamicDelegate;
protected:
	// Called when the game starts
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

	/*	taskid, receive from command param with exe start	*/
	UPROPERTY(EditAnywhere, Category = "P")
		FString Command_taskid;
	UPROPERTY(VisibleAnywhere, Category = "P")
		FString PXY_ReceiveData;
	/*
		datachannel接口都是异步的

		lr_client_start 返回成功只是说明接口创建成功

		是否连接成功需要看接口调用的回调函数,如果失败了 请查看on_disconnected的参数

	*/
	UFUNCTION(BlueprintCallable, Category = "P")
		static int PXY_Client_Start(FString TaskID);

	/*

		lr_client_send 发送字符串 时请 请保证 字符串是utf8编码,长度算上\0
		发送成功 返回值为发送的长度
		失败 请查看返回值
	*/
	UFUNCTION(BlueprintCallable, Category = "P")
		static int PXY_Client_SendText(FString SendData);
	UFUNCTION(BlueprintCallable, Category = "P")
		static int PXY_Client_SendBinary(TArray<uint8> SendData);
	/*

		结束调用lr_client_stop
	*/
	UFUNCTION(BlueprintCallable, Category = "P")
		static void PXY_Client_Stop();

	static void cc_on_connected();
	//回调事件,接收到数据时调用此函数
	static void  cc_on_data(data_type type, const char* data, int size);
	static void cc_on_disconnected(enum ErrorCode code);

	static UPXYDataChannelComponent* pThis;//静态对象指针
};
UPXYDataChannelComponent* UPXYDataChannelComponent::pThis = NULL;

PXYDataChannelComponent.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "PXYDataChannelComponent.h"

// Sets default values for this component's properties
UPXYDataChannelComponent::UPXYDataChannelComponent()
{
	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
	// off to improve performance if you don't need them.
	PrimaryComponentTick.bCanEverTick = true;
	pThis = this;
	// ...
}


// Called when the game starts
void UPXYDataChannelComponent::BeginPlay()
{
	Super::BeginPlay();

	// ...
	
}


// Called every frame
void UPXYDataChannelComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	// ...
}

int UPXYDataChannelComponent::PXY_Client_Start(FString TaskID)
{
	if (TaskID == "")
	{
		TaskID = "123456";
	}

	if (XR_SUCCESS != lr_client_start(TCHAR_TO_ANSI(*TaskID), cc_on_connected, cc_on_data, cc_on_disconnected))
	{
		return -1;
	}
	return 0;
}
int UPXYDataChannelComponent::PXY_Client_SendText(FString SendData)
{

	int sendsize;
	sendsize = lr_client_send(DATA_STRING, TCHAR_TO_ANSI(*SendData), SendData.Len());
	return sendsize;

}
int UPXYDataChannelComponent::PXY_Client_SendBinary(TArray<uint8> SendData)
{
	int sendsize = 0;

	/*for (int32 i = 0; i < SendData.Num(); i++)
	{
		sendsize = lr_client_send(DATA_BIN, (const char*)SendData[i], sizeof(SendData[i]));
	}*/
	//sendsize = lr_client_send(DATA_BIN, (const char*)SendData[0], sizeof(SendData));
	/*
	const TArray<const char*> Content;
	for (int32 i = 0; i < Content.Num(); i++)
	{
		sendsize = lr_client_send(DATA_BIN, Content[i], sizeof(Content[i]));
	}
	*/

	//sendsize = lr_client_send(DATA_BIN, (CHAR*)SendData, sizeof(SendData));


	return  sendsize;

}
void UPXYDataChannelComponent::PXY_Client_Stop()
{
	lr_client_stop();
}

void UPXYDataChannelComponent::cc_on_connected()
{
	UE_LOG(LogTemp, Warning, TEXT("data channel connected!"));
}
void UPXYDataChannelComponent::cc_on_data(data_type type, const char* data, int size)
{
	if (type == DATA_STRING)
	{
		P_Component_Data = data;
		pThis->p_MuitDynamicDelegate.Broadcast(p_data_type::DATA_STRING, ANSI_TO_TCHAR(data));//回调函数中调用非静态成员函数

		UE_LOG(LogTemp, Warning, TEXT("接收到数据:recv data string:%s size:%d"), ANSI_TO_TCHAR(data), size);
	}
	else {
		UE_LOG(LogTemp, Warning, TEXT("接收到数据:recv data binary: size :%d"), size);

	}
}
void UPXYDataChannelComponent::cc_on_disconnected(enum ErrorCode code)
{
	UE_LOG(LogTemp, Warning, TEXT("data channel disconnected!"));

}

 

 

14 其中比较重要的是委托的实现,第三方示例中用的是C函数,一般是静态函数,无法直接调用UE4组件里的函数,反之,UE4组件里的函数也无法直接调用静态函数,因此UE4组件必须实例化一个,或者记录一个实例化指针。

即 .h文件中最后的部分

当然,还要在.cpp 中的构造函数中初始化记录一下实例指针

之后就可以通过实例指针来调用UE4组件中的非静态函数了,这样就达到了第三方回调函数 调用委托,在蓝图内显示收到的数据的 效果

15  使用方法 工程中随便建个Actor蓝图,add component 中选择PXYDataChannel。添加之后选中这个组件,在右侧EventGraph 视图里右键,选择 对应的Event即可,此时若通过第三方给我们发送数据,这个回调函数就会显示收到的数据

 

16测试结果 

 

 

 

 

本文地址:https://blog.csdn.net/u011407338/article/details/112846890

《集成平行云 数据通道 C++ sdk 到UE4.doc》

下载本文的Word格式文档,以方便收藏与打印。