Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 41 additions & 4 deletions tutorials/scripting/cpp/core_types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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``
Expand Down
Loading