Skip to content

[UE] Bug: 静态绑定CombineOverloads的函数带TArray<UStruct>的情况运行时类型检查会失败 #2288

@watsonsong

Description

@watsonsong

前置阅读 | Pre-reading

Puer的版本 | Puer Version

master

UE的版本 | UE Version

5.7.2

发生在哪个平台 | Platform

Editor(win)

错误信息 | Error Message

注册一个静态绑定的测试函数,携带结构体数组(FSoftObjectPath)作为参数。
其中容器注册包含了UsingContainer以及RegisterTArray,代码如下:

struct FArrayOverloadTest
{
	static void TestOverload(const TArray<int>& Array)
	{
		UE_LOG(LogTemp, Warning, TEXT("[FArrayOverloadTest] TestOverload with array length: %d"), Array.Num());
	}

	static void TestOverload(const TArray<int>& Array, int Val)
	{
		UE_LOG(LogTemp, Warning, TEXT("[FArrayOverloadTest] TestOverload with array length: %d and value: %d"), Array.Num(), Val);
	}
};

UsingContainer(TArray<FSoftObjectPath>);

struct AutoRegisterForTest
{
    AutoRegisterForTest()
    {
        RegisterTArray(FSoftObjectPath);
        puerts::DefineClass<FArrayOverloadTest>()
             .Function("TestOverload", CombineOverloads(
                MakeOverload(void(*)(const TArray<FSoftObjectPath>& Array), &FArrayOverloadTest::TestOverload),
                MakeOverload(void(*)(const TArray<FSoftObjectPath>& Array, int), &FArrayOverloadTest::TestOverload)))
            .Register();
    }
}

AutoRegisterForTest _AutoRegisterForTest_;

尝试在js中测试调用会失败:

import * as cpp from 'cpp';
import * as UE from 'ue';

const assetArray = UE.NewArray(UE.SoftObjectPath);
cpp.FArrayOverloadTest.TestOverload(assetArray);

失败提示报错:

Puerts: Warning: (0x00000250120BE330) unhandledRejection,Error: invalid parameter!,Error: invalid parameter!

问题重现 | Bug reproduce

上述代码执行能重现问题。跟踪了一下调用栈:第一个参数在ArgumentsChecker的检查中失败了

template <std::size_t ND, typename... CArgs>
struct ArgumentsChecker<true, ND, CArgs...>
{
    static bool Check(typename API::ContextType context, typename API::CallbackInfoType info)
    {
        // ...

        // 这里失败了
        if (!ArgumentChecker<API, 0, ArgsLength - ND, CArgs...>::Check(info, context))
             return false;

        return true;
    }
};

最终是IsInstanceOfCppObject中的Template里面, HasInstance的判断失败了:

bool DataTransfer::IsInstanceOf(v8::Isolate* Isolate, const void* TypeId, v8::Local<v8::Value> JsObject)
{
    return JsObject->IsObject() &&
           IsolateData<ICppObjectMapper>(Isolate)->IsInstanceOfCppObject(Isolate, TypeId, JsObject.As<v8::Object>());
}

bool FCppObjectMapper::IsInstanceOfCppObject(v8::Isolate* Isolate, const void* TypeId, v8::Local<v8::Object> JsObject)
{
    // ...
    auto ClassDefinition = FindClassByID(TypeId);
    if (ClassDefinition)
    {
        // 能找到这个ClassDefinition和Template,但HasInstance失败了。
        auto Template = GetTemplateOfClass(Isolate, ClassDefinition);
        return Template->HasInstance(JsObject);
    }
}

似乎在UE.NewArray(UE.SoftObjectPath)去构造一个数组的时候,并没有触发GetTemplateOfClass,也没有向其中添加任何Instance。

Metadata

Metadata

Assignees

Labels

UnrealbugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions