How to implement macro library in C++?

Hello.

In some projects, designer create blueprint macro library(usually inherits Object). In macro library designer writes a lot of tools such as ‘A + B’,’Is Differenct’.

This macro library appears to be global. When I create a macro in library blueprint, in any actor blueprint I can find the macro created in ‘casting’ category.

I want to know how to implement it in C++.

Thanks!

Just to clarify: Are you looking to implement a macro library in C++ for use in blueprint? or do you want a C++ version of macro libraries to help you write C++ code?

If it’s the first, as far as I am aware, you can’t. Not exactly. Macro libraries aren’t actually universal, it’s limited to the class that the macro library derives from. Now if you inherit from Object, that’s everything. But if you inherit from something else you’d limit where those macros are available.

The closest thing you can get to it is a blueprint function library. They don’t have the same restriction as the macro library since you always inherit the UBlueprintFunctionLibrary class so the functions from them are available anywhere. You can create these in C++ by creating a class derived from UBlueprintFunctionLibrary and adding static functions to it that are blueprint callable.

If you’re asking about the second, there definitely isn’t. C++ doesn’t work that way. You could create a header with a bunch of common macros you use in multiple spots, but it wouldn’t function quite the same as the blueprint version. Also macros in C++ are generally discouraged as they break a lot of language rules. There are a few cases where they are the only option (conditional compilation, etc) but usually there’s a better option than macros.

Thanks for your answer, MagForceSeven. I want to make sure if I choose UBlueprintFunctionLibrary, how can I use it in such as ‘AMyCharacter.h/AMyCharacter.cpp’?
For example,

  1. Create MyCharacter class through C++ code.
  2. Create UBlueprintFunctionLibrary class and create func1 with ‘BlueprintCallable’(public) in it. In this step, can I call func1 in MyCharacter.cpp/MyCharacter.h just use ‘include’?
    I just want to use it as tool like FMath::xx.
  3. Create Derived Blueprint Class of MyCharacter. Can I call func1 in this derived blueprint as a blueprint node?
    (I’m new to C++. Please don’t mind my ignorance.)

Thank you very much again!

So, it’s worth noting that Blueprint function libraries as created in C++ are not really classes you instanciate, as such; they’re generally a whole series of static functions.

So, for instance, normally with your AMyCharacter class you defined in MyCharacter.cpp/MyCharacter.h, you create instances of that class. There could be 2, 3, or 17 different AMyCharacter instances in the world at a time.

If you make an UMyBlueprintFunctions library, there is only one of it, and you call functions on it directly. Generally, this means you’ll need to pass in anything the library needs to work with. So yes, it would be like FMath::xx, to use your example. If I wanted to have a function where I would launch one of your characters into orbit, it would be something like this (and I apologize if I mess something up in this hypothetical code; it’s 2am here and I’m going on pure memory):

UCLASS()
class UMyBlueprintFunctions : public UBlueprintFunctionLibrary
{
    /**
     * @brief Launches a character into space.
     * Given a character and gravity, calculate the necessary escape velocity
     * to escape the gravity well, and apply it to the character. 
     * @param Victim The character to be launched.
     * @param ZGravity The downward gravity we want to escape.
     * @param EnterLEO Should we take pity and allow the victim to attain
     *    Low Earth Orbit, or leave them traveling onwards eternally?
     */
    UFUNCTION(BlueprintCallable, Category="My Very Useful Things")
    static void Yeet(AMyCharacter *Victim, float ZGravity, bool EnterLEO = false);

    // other functions
}

Then if you were in some other bit of code and had a character you wanted to launch into space…

#include "MyBlueprintFunctions.h"

void AMyAstronautCharacter::BecomeRocketman() 
{
   UMyBlueprintFunctions::Yeet(this, CurrentGravity, true);
}

Or whatever. (Again, it’s 2am. I accept no responsibility for the nature of my ridiculous example code.)

Meanwhile, the fact that you’ve got that UFUNCTION(BlueprintCallable) there means that these functions will show up (globally) for Blueprints as well; there will be a Yeet node that takes a character, a float value, and a boolean, and in the list of Blueprint nodes it would show up in a category called My Very Useful Things.

You could thus have some other bit of code – even in a blueprint – which could Yeet() a character.

Does that help a bit?

I’ll try not to repeat what Packetdancer said (even for 2am it’s all correct :wink: ), but to directly answer your questions:

Yes. You can write your static functions to use whatever functionality you want.

Yes, but to be clear you’ll be able to call it in any blueprint as a blueprint node. It will not be limited the way the macro libraries are in which blueprints it’s available from.

Not to confuse the issue, but if you have a native AMyCharacter class (side note, source files usually drop the A/U from the typename) you could get roughly the same behavior by making a static BlueprintCallable function in AMyCharacter. You wouldn’t have to create a separate function library.
It’s also possible that all you need is a blueprint callable non-static method in your class. Personally I don’t really use macros, their only real benefit over functions in blueprint seems to be that they allow for using latent nodes. Since latent nodes aren’t really a thing when writing C++ code, you can usually just write blueprint callable functions if you’re trying to do something in native.

1 Like

Cool!
Thanks for your help! Packetdancer and MagForceSeven.
Following your implementation, now I perfectly get a FunctionLibrary and I can call it in Blueprint. Yes indeed, I found that I still can call func in Library without using‘include’ in c++ code, in any actor blueprint. I think UE might have hidden its reference somewhere.
t2

It’s not hidden, per se. The fact that you extended UBlueprintFunctionLibrary was, in and of itself, what allows Unreal to see it everywhere in blueprints; that’s basically what UBlueprintFunctionLibrary exists to do. :slight_smile:

Glad it helped, though!