UnrealC++로 구조체(USTURCT)를 캐스트해 보기
10290 단어 위 4UnrealEnginecast구조UnrealC++
소개
UnrealC++에는 "Unreal Property System"이라는 리플렉션 시스템이 있습니다.
언리얼 프로퍼티 시스템 (반사)
리플렉션이란 런타임시 프로그램의 구조(클래스의 상속 관계나 어떤 함수나 변수를 가지고 있는지 등...) 취득하거나 설정하거나 할 수 있는 구조입니다.
리플렉션 (정보 공학)
표준 C++에는 현재 리플렉션 기능이 없지만 UnrealC++에는 자체 리플렉션 시스템이 내장되어 있으므로 문자열에서 클래스와 함수를 검색하거나 Cast 함수를 사용하여 클래스를 캐스팅 할 수 있습니다. .
구조체를 Cast 함수로 캐스트 해보십시오.
TestStructs.hUSTRUCT(BlueprintType)
struct FTestStructBase
{
GENERATED_BODY()
};
USTRUCT(BlueprintType)
struct FTestStructA : public FTestStructBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere)
int32 TestInteger;
};
USTRUCT(BlueprintType)
struct FTestStructB : public FTestStructBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere)
FString TestString;
};
USTRUCT(BlueprintType)
struct FTestStructC : public FTestStructBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere)
FVector TestVector;
};
우선은 베이스가 되는 구조체와 그 파생을 3개 정의해 보겠습니다.
TestFunctionLibrary.cppvoid TestFunction(const FTestStructBase& TestStruct)
{
if (FTestStructA* StructA = Cast<FTestStructA>(&TestStruct))
{
}
}
이렇게 일반 UClass처럼 Cast를 시도하면 다음 컴파일 오류가 발생합니다.
'To *TCastImpl<From,To,ECastType::UObjectToUObject>::DoCast(UObject *)': cannot convert argument 1 from 'From *' to 'UObject *'
Cast 함수를 사용할 수 있는 것은 UObject를 상속한 클래스와 같습니다. 당연히 UStruct이지만 구조체 자체는 UObject를 상속하지 않으므로이 함수를 사용할 수 없습니다.
구조체를 dynamic_cast로 캐스팅 해보기
Cast 함수를 사용할 수 없어도 C++에는 「dynamic_cast」가 있다! 그렇게 해 보겠습니다.
분명히 매크로로 대체되어 버리는 일반 dynamic_cast는 사용할 수없는 것 같습니다.
무엇으로 대체될까 하면 "UE4Casts_Private::DynamicCast"라는 함수로 바뀌는 것 같습니다.
Engine\Source\Runtime\CoreUObject\Public\Templates\Casts.h(476)#define dynamic_cast UE4Casts_Private::DynamicCast
4 종류 정도 DynamicCast 함수가 정의되어 있습니다만, 어쩐지 사용해 주었으면 하는 것 같은 분위기...
그리고 역시 사용할 수 없었습니다.
'dynamic_cast': 'FTestStructBase' is not a polymorphic type
구조체를 static_cast로 캐스트 해 봅니다.
안쪽의 손인 'static_cast'를 사용하여 ...
TestFunctionLibrary.cppvoid TestFunction(const FTestStructBase& TestStruct)
{
if (FTestStructA* StructA = static_cast<FTestStructA*>(&TestStruct))
{
}
}
static_cast는 포인터 유형을 다른 포인터 유형으로 강제 변환하므로 TestStruct 변수가 FTestStructA 유형이 아닌 경우에도 StructA는 nullptr이 되지 않습니다.
UScriptStruct::GetStructCPPName으로 얻은 이름 비교
USTRUCT 로 정의한 구조체에는 StaticStruct
함수가 포함되어 있어 이 함수로 UScriptStruct 를 취득할 수 있습니다.
그리고 GetStructCPPName
함수로부터 함수명 대로 구조체의 이름을 취득할 수 있습니다.
※추기 GetStructCPPName로 취할 수 있는 이름은 GetName으로 취할 수 있는 구조체명에 접두사의 F를 붙일 수 있으므로 GetName에서도 문제 없습니다.
이 방법에서는 이하와 같이 인수나 변수 정의로 형태가 정해져 있으면 부모의 구조체의 이름이 취득되어 버리기 때문에 사용할 수 없습니다.
TestFunctionLibrary.cppvoid TestFunction(FTestStructBase TestStruct)
{
if (UScriptStruct* ScriptStruct = InTestStruct.StaticStruct())
{
if (ScriptStruct->GetStructCPPName() == FTestStructA::StaticStruct()->GetStructCPPName())
{
}
}
}
그러나, 다음과 같이 프로퍼티의 주사로 지정의 구조체인지를 판정하는 경우에는 사용할 수 있습니다.
TestFunctionLibrary.cppvoid TestFunction(UObject* Owner)
{
for (TFieldIterator<FProperty> PropertyItr(Owner); PropertyItr; ++PropertyItr)
{
FProperty* Property = *PropertyItr;
if (auto StructProperty = CastField<FStructProperty>(Property))
{
if (auto ScriptStruct = StructProperty->Struct)
{
if (ScriptStruct->GetStructCPPName() == FTestStructA::StaticStruct()->GetStructCPPName())
{
}
}
}
}
}
결론
여러가지 시도한 결과 별로 좋은 방법을 찾을 수 없었습니다 ...
상속하여 사용한다면 구조체가 아닌 UObject를 상속하여 사용하는 것이 좋을 것 같습니다.
아무래도 구조체로 한다면 독자적으로 고유의 ID와 같은 것을 갖게 해 그것을 바탕으로 판정하는 등의 궁리가 필요할 것 같습니다.
뭔가 좋은 방법을 아시면 코멘트 등으로 가르쳐 주시면 감사하겠습니다.
Reference
이 문제에 관하여(UnrealC++로 구조체(USTURCT)를 캐스트해 보기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/Naotsun/items/02bad6e1abd160bb73e2
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
TestStructs.h
USTRUCT(BlueprintType)
struct FTestStructBase
{
GENERATED_BODY()
};
USTRUCT(BlueprintType)
struct FTestStructA : public FTestStructBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere)
int32 TestInteger;
};
USTRUCT(BlueprintType)
struct FTestStructB : public FTestStructBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere)
FString TestString;
};
USTRUCT(BlueprintType)
struct FTestStructC : public FTestStructBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere)
FVector TestVector;
};
우선은 베이스가 되는 구조체와 그 파생을 3개 정의해 보겠습니다.
TestFunctionLibrary.cpp
void TestFunction(const FTestStructBase& TestStruct)
{
if (FTestStructA* StructA = Cast<FTestStructA>(&TestStruct))
{
}
}
이렇게 일반 UClass처럼 Cast를 시도하면 다음 컴파일 오류가 발생합니다.
'To *TCastImpl<From,To,ECastType::UObjectToUObject>::DoCast(UObject *)': cannot convert argument 1 from 'From *' to 'UObject *'
Cast 함수를 사용할 수 있는 것은 UObject를 상속한 클래스와 같습니다. 당연히 UStruct이지만 구조체 자체는 UObject를 상속하지 않으므로이 함수를 사용할 수 없습니다.
구조체를 dynamic_cast로 캐스팅 해보기
Cast 함수를 사용할 수 없어도 C++에는 「dynamic_cast」가 있다! 그렇게 해 보겠습니다.
분명히 매크로로 대체되어 버리는 일반 dynamic_cast는 사용할 수없는 것 같습니다.
무엇으로 대체될까 하면 "UE4Casts_Private::DynamicCast"라는 함수로 바뀌는 것 같습니다.
Engine\Source\Runtime\CoreUObject\Public\Templates\Casts.h(476)#define dynamic_cast UE4Casts_Private::DynamicCast
4 종류 정도 DynamicCast 함수가 정의되어 있습니다만, 어쩐지 사용해 주었으면 하는 것 같은 분위기...
그리고 역시 사용할 수 없었습니다.
'dynamic_cast': 'FTestStructBase' is not a polymorphic type
구조체를 static_cast로 캐스트 해 봅니다.
안쪽의 손인 'static_cast'를 사용하여 ...
TestFunctionLibrary.cppvoid TestFunction(const FTestStructBase& TestStruct)
{
if (FTestStructA* StructA = static_cast<FTestStructA*>(&TestStruct))
{
}
}
static_cast는 포인터 유형을 다른 포인터 유형으로 강제 변환하므로 TestStruct 변수가 FTestStructA 유형이 아닌 경우에도 StructA는 nullptr이 되지 않습니다.
UScriptStruct::GetStructCPPName으로 얻은 이름 비교
USTRUCT 로 정의한 구조체에는 StaticStruct
함수가 포함되어 있어 이 함수로 UScriptStruct 를 취득할 수 있습니다.
그리고 GetStructCPPName
함수로부터 함수명 대로 구조체의 이름을 취득할 수 있습니다.
※추기 GetStructCPPName로 취할 수 있는 이름은 GetName으로 취할 수 있는 구조체명에 접두사의 F를 붙일 수 있으므로 GetName에서도 문제 없습니다.
이 방법에서는 이하와 같이 인수나 변수 정의로 형태가 정해져 있으면 부모의 구조체의 이름이 취득되어 버리기 때문에 사용할 수 없습니다.
TestFunctionLibrary.cppvoid TestFunction(FTestStructBase TestStruct)
{
if (UScriptStruct* ScriptStruct = InTestStruct.StaticStruct())
{
if (ScriptStruct->GetStructCPPName() == FTestStructA::StaticStruct()->GetStructCPPName())
{
}
}
}
그러나, 다음과 같이 프로퍼티의 주사로 지정의 구조체인지를 판정하는 경우에는 사용할 수 있습니다.
TestFunctionLibrary.cppvoid TestFunction(UObject* Owner)
{
for (TFieldIterator<FProperty> PropertyItr(Owner); PropertyItr; ++PropertyItr)
{
FProperty* Property = *PropertyItr;
if (auto StructProperty = CastField<FStructProperty>(Property))
{
if (auto ScriptStruct = StructProperty->Struct)
{
if (ScriptStruct->GetStructCPPName() == FTestStructA::StaticStruct()->GetStructCPPName())
{
}
}
}
}
}
결론
여러가지 시도한 결과 별로 좋은 방법을 찾을 수 없었습니다 ...
상속하여 사용한다면 구조체가 아닌 UObject를 상속하여 사용하는 것이 좋을 것 같습니다.
아무래도 구조체로 한다면 독자적으로 고유의 ID와 같은 것을 갖게 해 그것을 바탕으로 판정하는 등의 궁리가 필요할 것 같습니다.
뭔가 좋은 방법을 아시면 코멘트 등으로 가르쳐 주시면 감사하겠습니다.
Reference
이 문제에 관하여(UnrealC++로 구조체(USTURCT)를 캐스트해 보기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/Naotsun/items/02bad6e1abd160bb73e2
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
#define dynamic_cast UE4Casts_Private::DynamicCast
'dynamic_cast': 'FTestStructBase' is not a polymorphic type
안쪽의 손인 'static_cast'를 사용하여 ...
TestFunctionLibrary.cpp
void TestFunction(const FTestStructBase& TestStruct)
{
if (FTestStructA* StructA = static_cast<FTestStructA*>(&TestStruct))
{
}
}
static_cast는 포인터 유형을 다른 포인터 유형으로 강제 변환하므로 TestStruct 변수가 FTestStructA 유형이 아닌 경우에도 StructA는 nullptr이 되지 않습니다.
UScriptStruct::GetStructCPPName으로 얻은 이름 비교
USTRUCT 로 정의한 구조체에는 StaticStruct
함수가 포함되어 있어 이 함수로 UScriptStruct 를 취득할 수 있습니다.
그리고 GetStructCPPName
함수로부터 함수명 대로 구조체의 이름을 취득할 수 있습니다.
※추기 GetStructCPPName로 취할 수 있는 이름은 GetName으로 취할 수 있는 구조체명에 접두사의 F를 붙일 수 있으므로 GetName에서도 문제 없습니다.
이 방법에서는 이하와 같이 인수나 변수 정의로 형태가 정해져 있으면 부모의 구조체의 이름이 취득되어 버리기 때문에 사용할 수 없습니다.
TestFunctionLibrary.cppvoid TestFunction(FTestStructBase TestStruct)
{
if (UScriptStruct* ScriptStruct = InTestStruct.StaticStruct())
{
if (ScriptStruct->GetStructCPPName() == FTestStructA::StaticStruct()->GetStructCPPName())
{
}
}
}
그러나, 다음과 같이 프로퍼티의 주사로 지정의 구조체인지를 판정하는 경우에는 사용할 수 있습니다.
TestFunctionLibrary.cppvoid TestFunction(UObject* Owner)
{
for (TFieldIterator<FProperty> PropertyItr(Owner); PropertyItr; ++PropertyItr)
{
FProperty* Property = *PropertyItr;
if (auto StructProperty = CastField<FStructProperty>(Property))
{
if (auto ScriptStruct = StructProperty->Struct)
{
if (ScriptStruct->GetStructCPPName() == FTestStructA::StaticStruct()->GetStructCPPName())
{
}
}
}
}
}
결론
여러가지 시도한 결과 별로 좋은 방법을 찾을 수 없었습니다 ...
상속하여 사용한다면 구조체가 아닌 UObject를 상속하여 사용하는 것이 좋을 것 같습니다.
아무래도 구조체로 한다면 독자적으로 고유의 ID와 같은 것을 갖게 해 그것을 바탕으로 판정하는 등의 궁리가 필요할 것 같습니다.
뭔가 좋은 방법을 아시면 코멘트 등으로 가르쳐 주시면 감사하겠습니다.
Reference
이 문제에 관하여(UnrealC++로 구조체(USTURCT)를 캐스트해 보기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/Naotsun/items/02bad6e1abd160bb73e2
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
void TestFunction(FTestStructBase TestStruct)
{
if (UScriptStruct* ScriptStruct = InTestStruct.StaticStruct())
{
if (ScriptStruct->GetStructCPPName() == FTestStructA::StaticStruct()->GetStructCPPName())
{
}
}
}
void TestFunction(UObject* Owner)
{
for (TFieldIterator<FProperty> PropertyItr(Owner); PropertyItr; ++PropertyItr)
{
FProperty* Property = *PropertyItr;
if (auto StructProperty = CastField<FStructProperty>(Property))
{
if (auto ScriptStruct = StructProperty->Struct)
{
if (ScriptStruct->GetStructCPPName() == FTestStructA::StaticStruct()->GetStructCPPName())
{
}
}
}
}
}
여러가지 시도한 결과 별로 좋은 방법을 찾을 수 없었습니다 ...
상속하여 사용한다면 구조체가 아닌 UObject를 상속하여 사용하는 것이 좋을 것 같습니다.
아무래도 구조체로 한다면 독자적으로 고유의 ID와 같은 것을 갖게 해 그것을 바탕으로 판정하는 등의 궁리가 필요할 것 같습니다.
뭔가 좋은 방법을 아시면 코멘트 등으로 가르쳐 주시면 감사하겠습니다.
Reference
이 문제에 관하여(UnrealC++로 구조체(USTURCT)를 캐스트해 보기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/Naotsun/items/02bad6e1abd160bb73e2텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)