ah ok with that context it’s clearer.
a weak ptr is the oposite of what you need. as it doesn’t keep the object from being gcd.
also the definition has no uproperty. so it will get gcd anyway.
i don’t think you can use a sharedptr properly in that context without risking yourself to destroy it by mistake.
and i have 2 solutions.
but it’s important to note that whatever you use you have to make all the pointers in the chain UPROPERTY otherwise they’ll get gcd or dangling. and if you make a raw pointer (with “new”) use some sort of auto pointer (like shared pointer from ue).
if you are going to use a UObject it has to be managed by ue gc. if you make your own raw pointer use an auto pointer.
If you make intermediate objects, those objects need to be stored in a uproperty-tagged variable or they will be lost.
i struggled with that when implementing this callback wrapper.
solution 1 my recommended.
- Use a subsystem
- whenever you need a context use the GEditor/GEngine global variable. it’s a static that you can access from anywhere. you can get the context from there. it might be a bit more involved to get the PIE world though. there are functions for it.
check this Making sure you're not a bot!
solution 1.5
most wrappers around jni or external libraries i’ve came across (that are somewhat decent) use a subsystem. and handle all the bindings there. the subsystem owns the jni code.
for example wave vr or sentry (the two i remember now) have a “pure cpp” object. that it’s managed. created, destroyed, and referenced by the subsystem (SS).
all code in the game go through the SS. and the SS passes that through the pure cpp object, which in turn does the translation to the jni. at no point the JNI needs to access any ue stuff. it just interfaces with such pure cpp object.
if you need a callback you set it to the pure cpp obj.
you might need to do something like this, though i’d avoid it if i can.
i’m sure there are examples of this in the engine, i haven’t thought of one from the top of my head.
this is also super common when you have to create different classes/implementations for the same api so that your game runs on editor/desktop/android/etc.
solution 2
- use a subsystem
- complement as singleton
- SS have a init/ deinit(forgot the name) functions. just keep a static pointer and set it to “this”/nullptr on such functions. like a regular singleton.
- it will work for ue code (use as subsystem), and will work for jni if you need a pointer.
- just be super careful in checking the pointer as it could get destroyed not by you. and make super sure you set it to nullptr so that it doesn’t become dangling.
-
- if you do it properly in the init/deinit functions you "should"
be safe.
- if you do it properly in the init/deinit functions you "should"
- i actually think this is better than solution 1.5 unless your jni static code is very large, verbose, and has to do a lot of translation. (like wavevr for example).
i can think of another way without using a ss, but i wouldn’t recommend it. since you need to account for PIE and Editor worlds which both exists during editor.
hope this helps.