diff options
| -rw-r--r-- | binding_generator.py | 10 | ||||
| -rw-r--r-- | gdextension/extension_api.json | 15 | ||||
| -rw-r--r-- | gdextension/gdextension_interface.h | 17 | ||||
| -rw-r--r-- | include/godot_cpp/core/class_db.hpp | 9 | ||||
| -rw-r--r-- | include/godot_cpp/core/object.hpp | 1 | ||||
| -rw-r--r-- | include/godot_cpp/godot.hpp | 1 | ||||
| -rw-r--r-- | include/godot_cpp/templates/cowdata.hpp | 8 | ||||
| -rw-r--r-- | include/godot_cpp/variant/char_string.hpp | 125 | ||||
| -rw-r--r-- | src/core/class_db.cpp | 10 | ||||
| -rw-r--r-- | src/godot.cpp | 2 | ||||
| -rw-r--r-- | src/variant/char_string.cpp | 205 | ||||
| -rw-r--r-- | test/project/main.gd | 4 | ||||
| -rw-r--r-- | test/src/example.cpp | 5 | ||||
| -rw-r--r-- | test/src/example.h | 1 |
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); |
