godot-cpp
godot-cpp copied to clipboard
PackedByteArray can't init and pass to const Variant **
I can't pass PackedByteArray to Variant.call and get error with NIL Type
gdscript code:
$Example.SendRequest("connector.joingame", "aaa".to_ascii_buffer(), func(x :PackedByteArray):
if (x.size() == 0):
prints("ok")
else:
prints("nono")
)
c++ code:
....
String route = args[0]->operator String();
PackedByteArray tmpdata = args[1]->operator PackedByteArray();
Variant funcall = *args[2];
PackedByteArray tmpVar;
Variant result;
GDNativeCallError err;
std::array<const GDNativeVariantPtr, sizeof(PackedByteArray)> call_args = { &tmpVar };
funcall.call("call", (const Variant **)call_args.data(), 1, result, err);
String route = args[0]->operator String();
PackedByteArray tmpdata = args[1]->operator PackedByteArray();
Variant funcall = *args[2];
PackedByteArray tmpVar;
Variant qqt = tmpVar;
const auto **argptr = (const Variant **)alloca(sizeof(Variant *));
argptr[0] = &qqt;
Variant result;
GDNativeCallError err;
funcall .call("call", argptr, 1, result, err);
this code can get good result...
but if i wan't to save funcall to funcsmap,and wait for the next response from server,the funcall will be memfree, so what can i do to call lambda functions async?
here is my code
String route = args[0]->operator String();
PackedByteArray tmpdata = args[1]->operator PackedByteArray();
Variant funcall = *args[2];
return pitayaClient.SendRequest(route.ascii().get_data(), const_cast<uint8_t *>(tmpdata.ptr()), tmpdata.size(), [&callab](const uint8_t* data, size_t length) {
UtilityFunctions::print("run call back len:" + length);
PackedByteArray tmpVar;
if (length != 0) {
tmpVar.resize(length);
memcpy(tmpVar.ptrw(), data, length);
}
Variant qqt = tmpVar;
const auto **argptr = (const Variant **)alloca(sizeof(Variant *));
argptr[0] = &qqt;
Variant result;
GDNativeCallError err;
callab.call("call", argptr, 1, result, err);
});
sendRequest will save c++ lambda function to map, and use catched temp funcall to call gdscript call
I solved by code,and can get successful result without memory leak
gdscript code
$Example.AddRouteOnMessage("onMessage", func(packMsg: PackedByteArray):
print(packMsg.get_string_from_ascii())
)
c++ code
if (arg_count != 2) {
error.error = GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS;
error.expected = 2;
}
String route = args[0]->operator String();
Variant funcall = *args[1]; // args[1] is lambda but godot-cpp doesn't have it,so I should call it by Variant
// callab = Variant(funcall) avoid memory free, and add RefCount to let godot know when to free it
// mutable should add , because c++ lambda capture vars by const
// finally gdscript lambda can be stored into maps, and be called in future with no Null pointer or Nil type
pitayaClient.AddRouteOnMessage(route.ascii().get_data(),
[this, callab = Variant(funcall)](const uint8_t* data, size_t length) mutable {
PackedByteArray tmpVar;
if (length != 0) {
tmpVar.resize(length);
memcpy(tmpVar.ptrw(), data, length);
}
Variant qqt = tmpVar;
const auto **argptr = (const Variant **)alloca(sizeof(Variant *));
argptr[0] = &qqt;
Variant result;
GDNativeCallError err;
// call_deferred to keep thread safety
callab.call("call_deferred", argptr, 1, result, err);
});