Skip to content
Merged
Show file tree
Hide file tree
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
26 changes: 26 additions & 0 deletions pygmt/clib/conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,32 @@ def sequence_to_ctypes_array(sequence: Sequence, ctype, size: int) -> ctp.Array
return (ctype * size)(*sequence)


def strings_to_ctypes_array(strings: Sequence[str]) -> ctp.Array:
"""
Convert a sequence (e.g., a list) of strings into a ctypes array.

Parameters
----------
strings
A sequence of strings.

Returns
-------
ctypes_array
A ctypes array of strings.

Examples
--------
>>> strings = ["first", "second", "third"]
>>> ctypes_array = strings_to_ctypes_array(strings)
>>> type(ctypes_array)
<class 'pygmt.clib.conversion.c_char_p_Array_3'>
>>> [s.decode() for s in ctypes_array]
['first', 'second', 'third']
"""
return (ctp.c_char_p * len(strings))(*[s.encode() for s in strings])


def array_to_datetime(array):
"""
Convert a 1-D datetime array from various types into numpy.datetime64.
Expand Down
14 changes: 5 additions & 9 deletions pygmt/clib/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
as_c_contiguous,
dataarray_to_matrix,
sequence_to_ctypes_array,
strings_to_ctypes_array,
vectors_to_arrays,
)
from pygmt.clib.loading import load_libgmt
Expand Down Expand Up @@ -897,13 +898,9 @@ def put_vector(self, dataset, column, vector):

gmt_type = self._check_dtype_and_dim(vector, ndim=1)
if gmt_type in (self["GMT_TEXT"], self["GMT_DATETIME"]):
vector_pointer = (ctp.c_char_p * len(vector))()
if gmt_type == self["GMT_DATETIME"]:
vector_pointer[:] = np.char.encode(
np.datetime_as_string(array_to_datetime(vector))
)
else:
vector_pointer[:] = np.char.encode(vector)
vector = np.datetime_as_string(array_to_datetime(vector))
vector_pointer = strings_to_ctypes_array(vector)
else:
vector_pointer = vector.ctypes.data_as(ctp.c_void_p)
status = c_put_vector(
Expand Down Expand Up @@ -960,13 +957,12 @@ def put_strings(self, dataset, family, strings):
restype=ctp.c_int,
)

strings_pointer = (ctp.c_char_p * len(strings))()
strings_pointer[:] = np.char.encode(strings)

family_int = self._parse_constant(
family, valid=FAMILIES, valid_modifiers=METHODS
)

strings_pointer = strings_to_ctypes_array(strings)

status = c_put_strings(
self.session_pointer, family_int, dataset, strings_pointer
)
Expand Down