Error linking NewObject<UMaterialExpressionRotator>

I’ve created some other expressions like


UMaterialExpressionTextureCoordinate* TexcoordExpression = NewObject<UMaterialExpressionTextureCoordinate>(UnrealMaterial);

but when I try to create a rotator like:


UMaterialExpressionRotator *Rotator = NewObject<UMaterialExpressionRotator>(UnrealMaterial);

I get a linking error:


error LNK2019: unresolved external symbol "private: static class UClass * __cdecl UMaterialExpressionRotator::GetPrivateStaticClass(wchar_t const *)" (?GetPrivateStaticClass@UMaterialExpressionRotator@@CAPEAVUClass@@PEB_W@Z) referenced in function "public: static class UClass * __cdecl UMaterialExpressionRotator::StaticClass(void)" (?StaticClass@UMaterialExpressionRotator@@SAPEAVUClass@@XZ)

Any though on this?

Thanks in advance

Same for fresnel
error LNK2019: unresolved external symbol “private: static class UClass * __cdecl UMaterialExpressionFresnel::GetPrivateStaticClass(wchar_t const *)” (?GetPrivateStaticClass@UMaterialExpressionFresnel@@CAPEAVUClass@@PEB_W@Z) referenced in function “public: static class UClass * __cdecl UMaterialExpressionFresnel::StaticClass(void)” (?StaticClass@UMaterialExpressionFresnel@@SAPEAVUClass@@XZ)

:confused:

It looks I’m not the first one with this issue, unfortunatly there is no reply:
https://answers.unrealengine.com/search.html?q=UMaterialExpressionFresnel&c=&type=question+OR+idea&lang=en&sort=relevance&author=&productVer=default&questionStatus=all

This is essentially the same issue as this: LNK2019 unresolved external symbol
The solution here (instead of adding ENGINE_API) would be to add MATERIALS_API (or MinimalAPI in the UCLASS macro above the class). If you look at UMaterialExpressionTextureCoordinate you’ll find the MinimalAPI class specifier, while UMaterialExpressionRotator and UMaterialExpressionFresnel (and probably others) don’t.

Of course you’ll also have to specify the module “Materials” as a dependency in your .Build.cs file but since you’ve used UMaterialExpressionTextureCoordinate before I guess you know that already :slight_smile:

Thank you so much I’ll try that later!

Btw that’s a bit strange that some MaterialExpression are in a different module than the others.

:frowning:
I’ve added MinimalAPI to my UCLASS and I had no luck also I didn’t manage to add “materials” to module dependencies: 1>EXEC : error : Couldn’t find module rules file for module ‘Materials’.

In the example post you spotted the solution was to add it to minimal api and recompile the full package but I think this is not a really nice solution since it should be done each time a new version is released.

Thank you anyway , any other idea?

They are not in different modules. I didn’t look close enough and accidentally thought there was a separate Materials module. It should have been the “Engine” module (which has a “Materials” subfolder). So try that instead. My bad, I’m sorry about that.

Did you recompile the engine after adding MinimalAPI?

As for having to do this each time there’s a new engine version, that’s true of course and can get annoying.
For me personally it’s no big deal to rebuild the engine (if you can spare the time it takes to do so) and integrate custom engine changes or additions I’ve made to new releases. I’m not immediately updating engine versions whenever they are released so I don’t have to do this very often. Also git helps a lot with this.

I have a doubt, since my plugin is an editor plugin, if I recompile it, it will work for me… but for others?

Yeah if you’re writing a plugin to be distributed, then engine modifications aren’t really an option.
Unfortunately if it has not been exported though, there’s nothing else you can do. My suggestion would be to submit a simple pull request at Github with the added export macro. If the class is one that people may reasonably want to use, they will generally accept such a request, though it will likely take a while to see it come through.

Come to think of it, there is actually a workaround if you really, really need it. You should be able to leverage UE4’s reflection system to construct your object without needing the class to be exported. You’ll be a bit limited in terms of what aspects of the class you can access still, but any base class members, virtual/inline functions and I think also direct data members, should be okay.

Something like this:



UClass* TheClass = FindObject< UClass >(ANY_PACKAGE, TEXT("MaterialExpressionRotator"));

// This will create a rotator, but the pointer you get back is to base class.
UMaterialExpression* RotatorExp = NewObject<UMaterialExpression>(UnrealMaterial, TheClass);

// I think you can do this, but it's possible Cast requires the class to be exported, not sure.
UMaterialExpressionRotator* Rotator = Cast< UMaterialExpressionRotator >(RotatorExp);


Great idea to do it that way. I as well would be interested to know if that (Cast<>) works or not. So please let us know if you’re having any success with this route. Thank you.

I did do something like this when I faced a similar issue a while back, but I can’t remember how exactly it worked out. In theory though, even if the UE4 cast requires the class to be exported, a static_cast should work here too.

In that case I guess Cast<> should work. Looking at “Engine/Source/Runtime/CoreUObject/Public/Templates/Casts.h” Cast<From, To> calls TCastImpl<From, To>::DoWork which should use the partial specialization TCastImpl<From, To, ECastType::UObjectToUObject> with From = UMaterialExpression and To = UMaterialExpressionRotator which will use a C-style cast (if the From* Src is valid and Src->IsA<To>()). And for the C-style cast static_cast should apply if I’m not mistaken.

In that case I suspect it would fail, since IsA< To > will I think need to know type information for the class that isn’t exported.

static_cast doesn’t do any runtime type checking so should be cool, and we know in this case that the object really should be of the target type. And we don’t have to worry about multiple inheritance with UObjects. So it probably safe, ish!

Cast<> needs the symbols but the old fashioned

worked like a charm!

Thank you so much, I owe you a beer!

Cool, no worries. Leffe Brune please!

Right, I didn’t check IsA :o :rolleyes:

And thanks again for posting your final solution.