summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--binding_generator.py10
-rw-r--r--gdextension/extension_api.json15
-rw-r--r--gdextension/gdextension_interface.h17
-rw-r--r--include/godot_cpp/core/class_db.hpp9
-rw-r--r--include/godot_cpp/core/object.hpp1
-rw-r--r--include/godot_cpp/godot.hpp1
-rw-r--r--include/godot_cpp/templates/cowdata.hpp8
-rw-r--r--include/godot_cpp/variant/char_string.hpp125
-rw-r--r--src/core/class_db.cpp10
-rw-r--r--src/godot.cpp2
-rw-r--r--src/variant/char_string.cpp205
-rw-r--r--test/project/main.gd4
-rw-r--r--test/src/example.cpp5
-rw-r--r--test/src/example.h1
14 files changed, 233 insertions, 180 deletions
diff --git a/binding_generator.py b/binding_generator.py
index d04c698..acc625d 100644
--- a/binding_generator.py
+++ b/binding_generator.py
@@ -1453,9 +1453,8 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
if is_singleton:
result.append(f"{class_name} *{class_name}::get_singleton() {{")
- result.append(f"\tconst StringName _gde_class_name = {class_name}::get_class_static();")
result.append(
- "\tstatic GDExtensionObjectPtr singleton_obj = internal::gdextension_interface_global_get_singleton(_gde_class_name._native_ptr());"
+ f"\tstatic GDExtensionObjectPtr singleton_obj = internal::gdextension_interface_global_get_singleton({class_name}::get_class_static()._native_ptr());"
)
result.append("#ifdef DEBUG_ENABLED")
result.append("\tERR_FAIL_COND_V(singleton_obj == nullptr, nullptr);")
@@ -1480,10 +1479,8 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
result.append(method_signature + " {")
# Method body.
- result.append(f"\tconst StringName _gde_class_name = {class_name}::get_class_static();")
- result.append(f'\tconst StringName _gde_method_name = "{method["name"]}";')
result.append(
- f'\tstatic GDExtensionMethodBindPtr _gde_method_bind = internal::gdextension_interface_classdb_get_method_bind(_gde_class_name._native_ptr(), _gde_method_name._native_ptr(), {method["hash"]});'
+ f'\tstatic GDExtensionMethodBindPtr _gde_method_bind = internal::gdextension_interface_classdb_get_method_bind({class_name}::get_class_static()._native_ptr(), StringName("{method["name"]}")._native_ptr(), {method["hash"]});'
)
method_call = "\t"
has_return = "return_value" in method and method["return_value"]["type"] != "void"
@@ -1773,9 +1770,8 @@ def generate_utility_functions(api, output_dir):
# Function body.
- source.append(f'\tconst StringName _gde_function_name = "{function["name"]}";')
source.append(
- f'\tstatic GDExtensionPtrUtilityFunction _gde_function = internal::gdextension_interface_variant_get_ptr_utility_function(_gde_function_name._native_ptr(), {function["hash"]});'
+ f'\tstatic GDExtensionPtrUtilityFunction _gde_function = internal::gdextension_interface_variant_get_ptr_utility_function(StringName("{function["name"]}")._native_ptr(), {function["hash"]});'
)
has_return = "return_type" in function and function["return_type"] != "void"
if has_return:
diff --git a/gdextension/extension_api.json b/gdextension/extension_api.json
index d089475..40481ed 100644
--- a/gdextension/extension_api.json
+++ b/gdextension/extension_api.json
@@ -2,10 +2,10 @@
"header": {
"version_major": 4,
"version_minor": 1,
- "version_patch": 0,
+ "version_patch": 1,
"version_status": "stable",
"version_build": "official",
- "version_full_name": "Godot Engine v4.1.stable.official"
+ "version_full_name": "Godot Engine v4.1.1.stable.official"
},
"builtin_class_sizes": [
{
@@ -53595,6 +53595,17 @@
}
},
{
+ "name": "get_camera_projection",
+ "is_const": true,
+ "is_vararg": false,
+ "is_static": false,
+ "is_virtual": false,
+ "hash": 2910717950,
+ "return_value": {
+ "type": "Projection"
+ }
+ },
+ {
"name": "get_fov",
"is_const": true,
"is_vararg": false,
diff --git a/gdextension/gdextension_interface.h b/gdextension/gdextension_interface.h
index 4d7bdf9..43931cc 100644
--- a/gdextension/gdextension_interface.h
+++ b/gdextension/gdextension_interface.h
@@ -2212,6 +2212,23 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant)
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassProperty)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionPropertyInfo *p_info, GDExtensionConstStringNamePtr p_setter, GDExtensionConstStringNamePtr p_getter);
/**
+ * @name classdb_register_extension_class_property_indexed
+ * @since 4.2
+ *
+ * Registers an indexed property on an extension class in the ClassDB.
+ *
+ * Provided struct can be safely freed once the function returns.
+ *
+ * @param p_library A pointer the library received by the GDExtension's entry point function.
+ * @param p_class_name A pointer to a StringName with the class name.
+ * @param p_info A pointer to a GDExtensionPropertyInfo struct.
+ * @param p_setter A pointer to a StringName with the name of the setter method.
+ * @param p_getter A pointer to a StringName with the name of the getter method.
+ * @param p_index The index to pass as the first argument to the getter and setter methods.
+ */
+typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionPropertyInfo *p_info, GDExtensionConstStringNamePtr p_setter, GDExtensionConstStringNamePtr p_getter, GDExtensionInt p_index);
+
+/**
* @name classdb_register_extension_class_property_group
* @since 4.1
*
diff --git a/include/godot_cpp/core/class_db.hpp b/include/godot_cpp/core/class_db.hpp
index 8eb1b55..0802a45 100644
--- a/include/godot_cpp/core/class_db.hpp
+++ b/include/godot_cpp/core/class_db.hpp
@@ -79,15 +79,6 @@ class ClassDB {
friend class godot::GDExtensionBinding;
public:
- struct PropertySetGet {
- int index;
- StringName setter;
- StringName getter;
- MethodBind *_setptr;
- MethodBind *_getptr;
- Variant::Type type;
- };
-
struct ClassInfo {
StringName name;
StringName parent_name;
diff --git a/include/godot_cpp/core/object.hpp b/include/godot_cpp/core/object.hpp
index d66e388..4e85e4d 100644
--- a/include/godot_cpp/core/object.hpp
+++ b/include/godot_cpp/core/object.hpp
@@ -49,6 +49,7 @@
#define ADD_GROUP(m_name, m_prefix) godot::ClassDB::add_property_group(get_class_static(), m_name, m_prefix)
#define ADD_SUBGROUP(m_name, m_prefix) godot::ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix)
#define ADD_PROPERTY(m_property, m_setter, m_getter) godot::ClassDB::add_property(get_class_static(), m_property, m_setter, m_getter)
+#define ADD_PROPERTYI(m_property, m_setter, m_getter, m_index) godot::ClassDB::add_property(get_class_static(), m_property, m_setter, m_getter, m_index)
namespace godot {
diff --git a/include/godot_cpp/godot.hpp b/include/godot_cpp/godot.hpp
index 2e28ad3..59aa150 100644
--- a/include/godot_cpp/godot.hpp
+++ b/include/godot_cpp/godot.hpp
@@ -173,6 +173,7 @@ extern "C" GDExtensionInterfaceClassdbRegisterExtensionClass gdextension_interfa
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassMethod gdextension_interface_classdb_register_extension_class_method;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant gdextension_interface_classdb_register_extension_class_integer_constant;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassProperty gdextension_interface_classdb_register_extension_class_property;
+extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed gdextension_interface_classdb_register_extension_class_property_indexed;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassPropertyGroup gdextension_interface_classdb_register_extension_class_property_group;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassPropertySubgroup gdextension_interface_classdb_register_extension_class_property_subgroup;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassSignal gdextension_interface_classdb_register_extension_class_signal;
diff --git a/include/godot_cpp/templates/cowdata.hpp b/include/godot_cpp/templates/cowdata.hpp
index 1753687..18320d8 100644
--- a/include/godot_cpp/templates/cowdata.hpp
+++ b/include/godot_cpp/templates/cowdata.hpp
@@ -32,13 +32,13 @@
#define GODOT_COWDATA_HPP
#include <godot_cpp/classes/global_constants.hpp>
-#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/math.hpp>
#include <godot_cpp/core/memory.hpp>
#include <godot_cpp/templates/safe_refcount.hpp>
#include <cstring>
+#include <new>
namespace godot {
@@ -48,6 +48,9 @@ class Vector;
template <class T, class V>
class VMap;
+template <class T>
+class CharStringT;
+
// Silence a false positive warning (see GH-52119).
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
@@ -62,6 +65,9 @@ class CowData {
template <class TV, class VV>
friend class VMap;
+ template <class TS>
+ friend class CharStringT;
+
private:
mutable T *_ptr = nullptr;
diff --git a/include/godot_cpp/variant/char_string.hpp b/include/godot_cpp/variant/char_string.hpp
index fa58bbd..f8f5169 100644
--- a/include/godot_cpp/variant/char_string.hpp
+++ b/include/godot_cpp/variant/char_string.hpp
@@ -31,83 +31,100 @@
#ifndef GODOT_CHAR_STRING_HPP
#define GODOT_CHAR_STRING_HPP
+#include <godot_cpp/templates/cowdata.hpp>
+
#include <cstddef>
#include <cstdint>
namespace godot {
-class CharString {
- friend class String;
-
- const char *_data = nullptr;
- int _length = 0;
-
- CharString(const char *str, int length);
-
-public:
- int length() const;
- const char *get_data() const;
-
- CharString(CharString &&p_str);
- void operator=(CharString &&p_str);
- CharString() {}
- ~CharString();
-};
+template <class T>
+class CharStringT;
-class Char16String {
- friend class String;
+template <class T>
+class CharProxy {
+ template <class TS>
+ friend class CharStringT;
- const char16_t *_data = nullptr;
- int _length = 0;
+ const int _index;
+ CowData<T> &_cowdata;
+ static inline const T _null = 0;
- Char16String(const char16_t *str, int length);
+ _FORCE_INLINE_ CharProxy(const int &p_index, CowData<T> &p_cowdata) :
+ _index(p_index),
+ _cowdata(p_cowdata) {}
public:
- int length() const;
- const char16_t *get_data() const;
-
- Char16String(Char16String &&p_str);
- void operator=(Char16String &&p_str);
- Char16String() {}
- ~Char16String();
-};
+ _FORCE_INLINE_ CharProxy(const CharProxy<T> &p_other) :
+ _index(p_other._index),
+ _cowdata(p_other._cowdata) {}
-class Char32String {
- friend class String;
+ _FORCE_INLINE_ operator T() const {
+ if (unlikely(_index == _cowdata.size())) {
+ return _null;
+ }
- const char32_t *_data = nullptr;
- int _length = 0;
+ return _cowdata.get(_index);
+ }
- Char32String(const char32_t *str, int length);
+ _FORCE_INLINE_ const T *operator&() const {
+ return _cowdata.ptr() + _index;
+ }
-public:
- int length() const;
- const char32_t *get_data() const;
+ _FORCE_INLINE_ void operator=(const T &p_other) const {
+ _cowdata.set(_index, p_other);
+ }
- Char32String(Char32String &&p_str);
- void operator=(Char32String &&p_str);
- Char32String() {}
- ~Char32String();
+ _FORCE_INLINE_ void operator=(const CharProxy<T> &p_other) const {
+ _cowdata.set(_index, p_other.operator T());
+ }
};
-class CharWideString {
+template <class T>
+class CharStringT {
friend class String;
- const wchar_t *_data = nullptr;
- int _length = 0;
-
- CharWideString(const wchar_t *str, int length);
+ CowData<T> _cowdata;
+ static inline const T _null = 0;
public:
- int length() const;
- const wchar_t *get_data() const;
-
- CharWideString(CharWideString &&p_str);
- void operator=(CharWideString &&p_str);
- CharWideString() {}
- ~CharWideString();
+ _FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); }
+ _FORCE_INLINE_ const T *ptr() const { return _cowdata.ptr(); }
+ _FORCE_INLINE_ int size() const { return _cowdata.size(); }
+ Error resize(int p_size) { return _cowdata.resize(p_size); }
+
+ _FORCE_INLINE_ T get(int p_index) const { return _cowdata.get(p_index); }
+ _FORCE_INLINE_ void set(int p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); }
+ _FORCE_INLINE_ const T &operator[](int p_index) const {
+ if (unlikely(p_index == _cowdata.size())) {
+ return _null;
+ }
+
+ return _cowdata.get(p_index);
+ }
+ _FORCE_INLINE_ CharProxy<T> operator[](int p_index) { return CharProxy<T>(p_index, _cowdata); }
+
+ _FORCE_INLINE_ CharStringT() {}
+ _FORCE_INLINE_ CharStringT(const CharStringT<T> &p_str) { _cowdata._ref(p_str._cowdata); }
+ _FORCE_INLINE_ void operator=(const CharStringT<T> &p_str) { _cowdata._ref(p_str._cowdata); }
+ _FORCE_INLINE_ CharStringT(const T *p_cstr) { copy_from(p_cstr); }
+
+ void operator=(const T *p_cstr);
+ bool operator<(const CharStringT<T> &p_right) const;
+ CharStringT<T> &operator+=(T p_char);
+ int length() const { return size() ? size() - 1 : 0; }
+ const T *get_data() const;
+ operator const T *() const { return get_data(); };
+
+protected:
+ void copy_from(const T *p_cstr);
};
+typedef CharStringT<char> CharString;
+typedef CharStringT<char16_t> Char16String;
+typedef CharStringT<char32_t> Char32String;
+typedef CharStringT<wchar_t> CharWideString;
+
} // namespace godot
#endif // GODOT_CHAR_STRING_HPP
diff --git a/src/core/class_db.cpp b/src/core/class_db.cpp
index e8bb40c..159c031 100644
--- a/src/core/class_db.cpp
+++ b/src/core/class_db.cpp
@@ -105,15 +105,7 @@ void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinf
p_pinfo.usage, // DEFAULT //uint32_t usage;
};
- PropertySetGet setget;
- setget.setter = p_setter;
- setget.getter = p_getter;
- setget._setptr = setter;
- setget._getptr = getter;
- setget.index = p_index;
- setget.type = p_pinfo.type;
-
- internal::gdextension_interface_classdb_register_extension_class_property(internal::library, info.name._native_ptr(), &prop_info, setget.setter._native_ptr(), setget.getter._native_ptr());
+ internal::gdextension_interface_classdb_register_extension_class_property_indexed(internal::library, info.name._native_ptr(), &prop_info, p_setter._native_ptr(), p_getter._native_ptr(), p_index);
}
MethodBind *ClassDB::get_method(const StringName &p_class, const StringName &p_method) {
diff --git a/src/godot.cpp b/src/godot.cpp
index e6ad172..c85667f 100644
--- a/src/godot.cpp
+++ b/src/godot.cpp
@@ -178,6 +178,7 @@ GDExtensionInterfaceClassdbRegisterExtensionClass gdextension_interface_classdb_
GDExtensionInterfaceClassdbRegisterExtensionClassMethod gdextension_interface_classdb_register_extension_class_method = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant gdextension_interface_classdb_register_extension_class_integer_constant = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassProperty gdextension_interface_classdb_register_extension_class_property = nullptr;
+GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed gdextension_interface_classdb_register_extension_class_property_indexed = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassPropertyGroup gdextension_interface_classdb_register_extension_class_property_group = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassPropertySubgroup gdextension_interface_classdb_register_extension_class_property_subgroup = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassSignal gdextension_interface_classdb_register_extension_class_signal = nullptr;
@@ -360,6 +361,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
LOAD_PROC_ADDRESS(classdb_register_extension_class_method, GDExtensionInterfaceClassdbRegisterExtensionClassMethod);
LOAD_PROC_ADDRESS(classdb_register_extension_class_integer_constant, GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant);
LOAD_PROC_ADDRESS(classdb_register_extension_class_property, GDExtensionInterfaceClassdbRegisterExtensionClassProperty);
+ LOAD_PROC_ADDRESS(classdb_register_extension_class_property_indexed, GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed);
LOAD_PROC_ADDRESS(classdb_register_extension_class_property_group, GDExtensionInterfaceClassdbRegisterExtensionClassPropertyGroup);
LOAD_PROC_ADDRESS(classdb_register_extension_class_property_subgroup, GDExtensionInterfaceClassdbRegisterExtensionClassPropertySubgroup);
LOAD_PROC_ADDRESS(classdb_register_extension_class_signal, GDExtensionInterfaceClassdbRegisterExtensionClassSignal);
diff --git a/src/variant/char_string.cpp b/src/variant/char_string.cpp
index 0c8cd0f..856037c 100644
--- a/src/variant/char_string.cpp
+++ b/src/variant/char_string.cpp
@@ -38,116 +38,120 @@
#include <godot_cpp/godot.hpp>
#include <cmath>
+#include <string>
namespace godot {
-int CharString::length() const {
- return _length;
-}
-
-const char *CharString::get_data() const {
- return _data;
-}
-
-CharString::CharString(CharString &&p_str) {
- SWAP(_length, p_str._length);
- SWAP(_data, p_str._data);
-}
+template <typename L, typename R>
+_FORCE_INLINE_ bool is_str_less(const L *l_ptr, const R *r_ptr) {
+ while (true) {
+ const char32_t l = *l_ptr;
+ const char32_t r = *r_ptr;
+
+ if (l == 0 && r == 0) {
+ return false;
+ } else if (l == 0) {
+ return true;
+ } else if (r == 0) {
+ return false;
+ } else if (l < r) {
+ return true;
+ } else if (l > r) {
+ return false;
+ }
-void CharString::operator=(CharString &&p_str) {
- SWAP(_length, p_str._length);
- SWAP(_data, p_str._data);
+ l_ptr++;
+ r_ptr++;
+ }
}
-CharString::CharString(const char *str, int length) :
- _data(str), _length(length) {}
-
-CharString::~CharString() {
- if (_data != nullptr) {
- memdelete_arr(_data);
+template <class T>
+bool CharStringT<T>::operator<(const CharStringT<T> &p_right) const {
+ if (length() == 0) {
+ return p_right.length() != 0;
}
-}
-int Char16String::length() const {
- return _length;
+ return is_str_less(get_data(), p_right.get_data());
}
-const char16_t *Char16String::get_data() const {
- return _data;
-}
+template <class T>
+CharStringT<T> &CharStringT<T>::operator+=(T p_char) {
+ const int lhs_len = length();
+ resize(lhs_len + 2);
-Char16String::Char16String(Char16String &&p_str) {
- SWAP(_length, p_str._length);
- SWAP(_data, p_str._data);
-}
+ T *dst = ptrw();
+ dst[lhs_len] = p_char;
+ dst[lhs_len + 1] = 0;
-void Char16String::operator=(Char16String &&p_str) {
- SWAP(_length, p_str._length);
- SWAP(_data, p_str._data);
+ return *this;
}
-Char16String::Char16String(const char16_t *str, int length) :
- _data(str), _length(length) {}
+template <class T>
+void CharStringT<T>::operator=(const T *p_cstr) {
+ copy_from(p_cstr);
+}
-Char16String::~Char16String() {
- if (_data != nullptr) {
- memdelete_arr(_data);
+template <>
+const char *CharStringT<char>::get_data() const {
+ if (size()) {
+ return &operator[](0);
+ } else {
+ return "";
}
}
-int Char32String::length() const {
- return _length;
+template <>
+const char16_t *CharStringT<char16_t>::get_data() const {
+ if (size()) {
+ return &operator[](0);
+ } else {
+ return u"";
+ }
}
-const char32_t *Char32String::get_data() const {
- return _data;
+template <>
+const char32_t *CharStringT<char32_t>::get_data() const {
+ if (size()) {
+ return &operator[](0);
+ } else {
+ return U"";
+ }
}
-Char32String::Char32String(Char32String &&p_str) {
- SWAP(_length, p_str._length);
- SWAP(_data, p_str._data);
+template <>
+const wchar_t *CharStringT<wchar_t>::get_data() const {
+ if (size()) {
+ return &operator[](0);
+ } else {
+ return L"";
+ }
}
-void Char32String::operator=(Char32String &&p_str) {
- SWAP(_length, p_str._length);
- SWAP(_data, p_str._data);
-}
+template <class T>
+void CharStringT<T>::copy_from(const T *p_cstr) {
+ if (!p_cstr) {
+ resize(0);
+ return;
+ }
-Char32String::Char32String(const char32_t *str, int length) :
- _data(str), _length(length) {}
+ size_t len = std::char_traits<T>::length(p_cstr);
-Char32String::~Char32String() {
- if (_data != nullptr) {
- memdelete_arr(_data);
+ if (len == 0) {
+ resize(0);
+ return;
}
-}
-int CharWideString::length() const {
- return _length;
-}
+ Error err = resize(++len); // include terminating null char
-const wchar_t *CharWideString::get_data() const {
- return _data;
-}
-
-CharWideString::CharWideString(CharWideString &&p_str) {
- SWAP(_length, p_str._length);
- SWAP(_data, p_str._data);
-}
+ ERR_FAIL_COND_MSG(err != OK, "Failed to copy C-string.");
-void CharWideString::operator=(CharWideString &&p_str) {
- SWAP(_length, p_str._length);
- SWAP(_data, p_str._data);
+ memcpy(ptrw(), p_cstr, len);
}
-CharWideString::CharWideString(const wchar_t *str, int length) :
- _data(str), _length(length) {}
-
-CharWideString::~CharWideString() {
- if (_data != nullptr) {
- memdelete_arr(_data);
- }
-}
+template class CharStringT<char>;
+template class CharStringT<char16_t>;
+template class CharStringT<char32_t>;
+template class CharStringT<wchar_t>;
// Custom String functions that are not part of bound API.
// It's easier to have them written in C++ directly than in a Python script that generates them.
@@ -228,56 +232,61 @@ String rtoss(double p_val) {
CharString String::utf8() const {
int length = internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), nullptr, 0);
int size = length + 1;
- char *cstr = memnew_arr(char, size);
- internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), cstr, length);
+ CharString str;
+ str.resize(size);
+ internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), str.ptrw(), length);
- cstr[length] = '\0';
+ str[length] = '\0';
- return CharString(cstr, length);
+ return str;
}
CharString String::ascii() const {
int length = internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), nullptr, 0);
int size = length + 1;
- char *cstr = memnew_arr(char, size);
- internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), cstr, length);
+ CharString str;
+ str.resize(size);
+ internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), str.ptrw(), length);
- cstr[length] = '\0';
+ str[length] = '\0';
- return CharString(cstr, length);
+ return str;
}
Char16String String::utf16() const {
int length = internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), nullptr, 0);
int size = length + 1;
- char16_t *cstr = memnew_arr(char16_t, size);
- internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), cstr, length);
+ Char16String str;
+ str.resize(size);
+ internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), str.ptrw(), length);
- cstr[length] = '\0';
+ str[length] = '\0';
- return Char16String(cstr, length);
+ return str;
}
Char32String String::utf32() const {
int length = internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), nullptr, 0);
int size = length + 1;
- char32_t *cstr = memnew_arr(char32_t, size);
- internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), cstr, length);
+ Char32String str;
+ str.resize(size);
+ internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), str.ptrw(), length);
- cstr[length] = '\0';
+ str[length] = '\0';
- return Char32String(cstr, length);
+ return str;
}
CharWideString String::wide_string() const {
int length = internal::gdextension_interface_string_to_wide_chars(_native_ptr(), nullptr, 0);
int size = length + 1;
- wchar_t *cstr = memnew_arr(wchar_t, size);
- internal::gdextension_interface_string_to_wide_chars(_native_ptr(), cstr, length);
+ CharWideString str;
+ str.resize(size);
+ internal::gdextension_interface_string_to_wide_chars(_native_ptr(), str.ptrw(), length);
- cstr[length] = '\0';
+ str[length] = '\0';
- return CharWideString(cstr, length);
+ return str;
}
String &String::operator=(const char *p_str) {
diff --git a/test/project/main.gd b/test/project/main.gd
index cdd8696..cedd512 100644
--- a/test/project/main.gd
+++ b/test/project/main.gd
@@ -82,6 +82,10 @@ func _ready():
# UtilityFunctions::str()
assert_equal(example.test_str_utility(), "Hello, World! The answer is 42")
+ # Test converting string to char* and doing comparison.
+ assert_equal(example.test_string_is_fourty_two("blah"), false)
+ assert_equal(example.test_string_is_fourty_two("fourty two"), true)
+
# PackedArray iterators
assert_equal(example.test_vector_ops(), 105)
diff --git a/test/src/example.cpp b/test/src/example.cpp
index 34ee355..fb47dd8 100644
--- a/test/src/example.cpp
+++ b/test/src/example.cpp
@@ -138,6 +138,7 @@ void Example::_bind_methods() {
ClassDB::bind_method(D_METHOD("test_node_argument"), &Example::test_node_argument);
ClassDB::bind_method(D_METHOD("test_string_ops"), &Example::test_string_ops);
ClassDB::bind_method(D_METHOD("test_str_utility"), &Example::test_str_utility);
+ ClassDB::bind_method(D_METHOD("test_string_is_fourty_two"), &Example::test_string_is_fourty_two);
ClassDB::bind_method(D_METHOD("test_vector_ops"), &Example::test_vector_ops);
ClassDB::bind_method(D_METHOD("test_bitfield", "flags"), &Example::test_bitfield);
@@ -299,6 +300,10 @@ String Example::test_str_utility() const {
return UtilityFunctions::str("Hello, ", "World", "! The answer is ", 42);
}
+bool Example::test_string_is_fourty_two(const String &p_string) const {
+ return strcmp(p_string.utf8().ptr(), "fourty two") == 0;
+}
+
int Example::test_vector_ops() const {
PackedInt32Array arr;
arr.push_back(10);
diff --git a/test/src/example.h b/test/src/example.h
index a330030..a84efed 100644
--- a/test/src/example.h
+++ b/test/src/example.h
@@ -117,6 +117,7 @@ public:
Example *test_node_argument(Example *p_node) const;
String test_string_ops() const;
String test_str_utility() const;
+ bool test_string_is_fourty_two(const String &p_str) const;
int test_vector_ops() const;
BitField<Flags> test_bitfield(BitField<Flags> flags);