Skip to content

Commit 4788781

Browse files
committed
godot-cpp: Explain that ptr()/ptrw() should be used to efficiently access Packed*Arrays
1 parent d6267ea commit 4788781

File tree

1 file changed

+41
-4
lines changed

1 file changed

+41
-4
lines changed

tutorials/scripting/cpp/core_types.rst

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,48 @@ Packed arrays
3030
~~~~~~~~~~~~~
3131

3232
While in Godot, the ``Packed*Array`` types are aliases of ``Vector``, in godot-cpp, they're their own types, using the
33-
Godot bindings. This is because these types, along with their methods, are exposed through the GDExtension interface,
34-
which would not be compatible with the templated nature of ``Vector``.
33+
Godot bindings. This is because ``Packed*Array`` are exposed to Godot and limited to only Godot types, whereas ``Vector``
34+
can hold any C++ type which Godot might not be able to understand.
3535

36-
In general though, the ``Packed*Array`` types work the same way as their ``Vector`` aliases. However, you should be
37-
aware that the ``Variant`` wrappers for ``Packed*Array`` treat them as pass-by-reference, while the ``Packed*Array``
36+
In general, the ``Packed*Array`` types work the same way as their ``Vector`` aliases, however, there are some notable
37+
differences.
38+
39+
Data access
40+
+++++++++++
41+
42+
``Vector`` keeps its data entirely within the GDExtension, whereas the ``Packed*Array`` types keep their data on the
43+
Godot side. This means that any time a ``Packed*Array`` is accessed, it needs to call into Godot.
44+
45+
To efficiently read or write a large amount of data into a ``Packed*Array``, you should called ``.ptr()`` (for reading)
46+
or ``.ptrw()`` (for writing) to get a pointer directly to the array's memory:
47+
48+
.. code-block:: cpp
49+
50+
// BAD!
51+
void my_bad_function(const PackedByteArray &p_array) {
52+
for (int i = 0; i < p_array.size(); i++) {
53+
// Each time this runs it needs to call into Godot.
54+
uint8_t byte = p_array[i];
55+
56+
// .. do something with the byte.
57+
}
58+
}
59+
60+
// GOOD :-)
61+
void my_good_function(const PackedByteArray &p_array) {
62+
const uint8_t *array_ptr = p_array.ptr();
63+
for (int i = 0; i < p_array.size(); i++) {
64+
// This directly accesses the memory!
65+
uint8_t byte = array_ptr[i];
66+
67+
// .. do something with the byte.
68+
}
69+
}
70+
71+
Copying
72+
+++++++
73+
74+
``Variant`` wrappers for ``Packed*Array`` treat them as pass-by-reference, while the ``Packed*Array``
3875
types themselves are pass-by-value (implemented as copy-on-write).
3976

4077
In addition, it may be of interest that GDScript calls use the ``Variant`` call interface: Any ``Packed*Array``

0 commit comments

Comments
 (0)