Skip to content

Commit 296b537

Browse files
committed
[lldb] Support the Python stable C API in PythonString::AsUTF8
This conditionally reimplements PythonString::AsUTF8 using PyUnicode_AsUTF8String instead of PyUnicode_AsUTF8AndSize. PyUnicode_AsUTF8AndSize caches the UTF-8 representation of the string in the Unicode object, which makes it more efficient and ties the lifetime of the data to the Python string. However, it was only added to the Stable API in Python 3.10. Older versions that want to use the Stable API must use PyUnicode_AsUTF8String in combination with ConstString.
1 parent 38542ef commit 296b537

File tree

1 file changed

+23
-5
lines changed

1 file changed

+23
-5
lines changed

lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -405,15 +405,33 @@ Expected<llvm::StringRef> PythonString::AsUTF8() const {
405405
if (!IsValid())
406406
return nullDeref();
407407

408-
Py_ssize_t size;
409-
const char *data;
408+
// PyUnicode_AsUTF8AndSize caches the UTF-8 representation of the string in
409+
// the Unicode object, which makes it more efficient and ties the lifetime of
410+
// the data to the Python string. However, it was only added to the Stable API
411+
// in Python 3.10. Older versions that want to use the Stable API must use
412+
// PyUnicode_AsUTF8String in combination with ConstString.
413+
#if defined(Py_LIMITED_API) && (Py_LIMITED_API < 0x030a0000)
414+
PyObject *py_bytes = PyUnicode_AsUTF8String(m_py_obj);
415+
if (!py_bytes)
416+
return exception();
417+
auto release_py_str =
418+
llvm::make_scope_exit([py_bytes] { Py_DECREF(py_bytes); });
419+
Py_ssize_t size = PyBytes_Size(py_bytes);
420+
const char *str = PyBytes_AsString(py_bytes);
421+
422+
if (!str)
423+
return exception();
410424

411-
data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
425+
return ConstString(str, size).GetStringRef();
426+
#else
427+
Py_ssize_t size;
428+
const char *str = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
412429

413-
if (!data)
430+
if (!str)
414431
return exception();
415432

416-
return llvm::StringRef(data, size);
433+
return llvm::StringRef(str, size);
434+
#endif
417435
}
418436

419437
size_t PythonString::GetSize() const {

0 commit comments

Comments
 (0)