Hey guys,
I have this bind:
proc setPropertyValuePtr*[T](property:FPropertyPtr, container : pointer, value : ptr T) : void {.importcpp: "SetPropertyValuePtr<'0>(@)", header:"UPropertyCaller.h".}
And using it like so:
setPropertyValuePtr[FString](prop, obj, value.addr)
However, Nim is producing:
SetPropertyValuePtr<void>(prop, ((void*) (obj)), (&value));
Any idea why? What am I doing wrong?
Thanks, Juan
The '0 means take the return value, which is void.
God I hate RST so much I can't seem to post the right answer but it's single quote asterisk three
Awesome, thanks! Didn't see that part of the docs until now. I just assumed the number were referring to the template args in Nim.
Thanks again!
Not sure if I should create another question for this, let me know if that's the case.
Im struggling with this signature:
proc makeTMap*[K, V]() : TMap[K, V] {.importcpp: "TMap<'*0, '*?>()", constructor .}
What should be used there instead of the "?"
Thanks,
Juan
The following works :
# Bar.h
#include <iostream>
template<typename K, typename V>
class Bar {
public:
Bar() {
std::cout << "Bar " << std::endl;
}
void doWithBar() {
std::cout << "doWithBar " << std::endl;
}
~Bar() {}
};
{.push header: "bar.h".}
proc test() {.importcpp: "test".}
type
Bar[K, V] {.importcpp: "Bar".} = object
proc makeBar*[K, V]() : Bar[K, V] {.importcpp: "'0()", constructor, cdecl.}
proc doWithBar*[K, V](self: Bar[K, V]) {.importcpp: "doWithBar", cdecl.}
{.pop.}
Thanks @Clonk!
proc cmakeBar*[K, V](k: typedesc[K], v: typedesc[V]) : Bar[K, V] {.importcpp: "Bar<'*1, '*2>()", constructor, cdecl.}
Does not look bad! will use it for now. It would be great to know if there is support in the syntax though. I was trying to look at the sources but couldnt find anything :/'0 means return type of the proc; in this case Bar[K, V].
That's why it's safe to use for a constructor because C++ constructor will always be named after their own type.
So doing - even if it's less intuitive - will work for every constructor.
proc makeBar*[K, V]() : Bar[K, V] {.importcpp: "'0()", constructor, cdecl.}
The second example that you seem to prefer just pass typedesc of argument to be able to extract type with the '*0..9 syntax.
To explain a bit further :
Just be careful with this option, as the "trampoline" proc
proc makeBar*[K, V]() : Bar[K, V] = cmakeBar(typedesc[K], typedesc[V])
may create unnecessary copies.
Generally speaking, when mapping C++ class to Nim's type - and especially when using C++ containers - a special consideration of what exactly happens in your memory is necessary because Nim's memory model and C++ memory model are not equivalent to one another.
For example if you use a C++ container TMap<K, V> and V is a Nim type with =sink; =copy defined then the C++ code will not call the Nim hook. In the same idea, Nim may sometimes make unnecessary copy of C++ class that C++ code knows how to optimize.
Hey @Clonk,
the syntax is more and less clear to me now. What isnt clear is if the workaround is a limitation or not.
On the hand, in NimForUE we are not using ref types at all (although we have ORC activated). Unreal has its own GC system so we just use ptrs, where everything is created in the cpp side of things. But not sure based on what you just said, if we should add a defensive mechanism where it warns you about using ref objects with UE's containers. Im not too concerned about a few the extra copies, after all unreal uses BPs which copies pretty much always, but Im concerned if it may cause memory leaks.
Any thoughts about it?
Thanks,
Juan
Unreal has its own GC system so we just use ptrs, where everything is created in the cpp side of things.
As long as you don't mix C++ memory model with Nim memory model you shouldn't have any issue.
The problem comes from Nim's =sink/=copy/=destroy hook not being called by C++ containers because C++ uses copy & move operator / constructor.
If you only handle C++ type (with a copy & move operator specified) or Nim's type that do not require =sink / =copy / =destroy you should be fine.