فهرست منبع

Merge pull request #11516 from dsnopek/godot-cpp-packedarrays-ptr

godot-cpp: Explain that `ptr()`/`ptrw()` should be used to efficiently access `Packed*Array`s
Max Hilbrunner 3 روز پیش
والد
کامیت
04609f757e
1فایلهای تغییر یافته به همراه41 افزوده شده و 4 حذف شده
  1. 41 4
      tutorials/scripting/cpp/core_types.rst

+ 41 - 4
tutorials/scripting/cpp/core_types.rst

@@ -30,11 +30,48 @@ Packed arrays
 ~~~~~~~~~~~~~
 
 While in Godot, the ``Packed*Array`` types are aliases of ``Vector``, in godot-cpp, they're their own types, using the
-Godot bindings. This is because these types, along with their methods, are exposed through the GDExtension interface,
-which would not be compatible with the templated nature of ``Vector``.
+Godot bindings. This is because ``Packed*Array`` are exposed to Godot and limited to only Godot types, whereas ``Vector``
+can hold any C++ type which Godot might not be able to understand.
 
-In general though, the ``Packed*Array`` types work the same way as their ``Vector`` aliases. However, you should be
-aware that the ``Variant`` wrappers for ``Packed*Array`` treat them as pass-by-reference, while the ``Packed*Array``
+In general, the ``Packed*Array`` types work the same way as their ``Vector`` aliases, however, there are some notable
+differences.
+
+Data access
++++++++++++
+
+``Vector`` keeps its data entirely within the GDExtension, whereas the ``Packed*Array`` types keep their data on the
+Godot side. This means that any time a ``Packed*Array`` is accessed, it needs to call into Godot.
+
+To efficiently read or write a large amount of data into a ``Packed*Array``, you should call ``.ptr()`` (for reading)
+or ``.ptrw()`` (for writing) to get a pointer directly to the array's memory:
+
+.. code-block:: cpp
+
+    // BAD!
+    void my_bad_function(const PackedByteArray &p_array) {
+        for (int i = 0; i < p_array.size(); i++) {
+            // Each time this runs it needs to call into Godot.
+            uint8_t byte = p_array[i];
+
+            // .. do something with the byte.
+        }
+    }
+
+    // GOOD :-)
+    void my_good_function(const PackedByteArray &p_array) {
+        const uint8_t *array_ptr = p_array.ptr();
+        for (int i = 0; i < p_array.size(); i++) {
+            // This directly accesses the memory!
+            uint8_t byte = array_ptr[i];
+
+            // .. do something with the byte.
+        }
+    }
+
+Copying
++++++++
+
+``Variant`` wrappers for ``Packed*Array`` treat them as pass-by-reference, while the ``Packed*Array``
 types themselves are pass-by-value (implemented as copy-on-write).
 
 In addition, it may be of interest that GDScript calls use the ``Variant`` call interface: Any ``Packed*Array``