pub fn interned_from_c_str(str: &CStr, persistent: bool) -> ZBox<Self> {
        let _lock = INTERNED_LOCK.lock();

        unsafe {
            let init = zend_string_init_interned.expect("`zend_string_init_interned` not ready");
            let ptr = init(str.as_ptr(), str.to_bytes().len() as _, persistent);

            ZBox::from_raw(
                ptr.as_mut()
                    .expect("Failed to allocate memory for new Zend string"),
            )
        }
    }
Creates a new interned Zend string from a [`CStr`].

An interned string is only ever stored once and is immutable. PHP stores
the string in an internal hashtable which stores the interned
strings.

As Zend hashtables are not thread-safe, a mutex is used to prevent two
interned strings from being created at the same time.

Interned strings are not used very often. You should almost always use a
regular zend string, except in the case that you know you will use a
string that PHP will already have interned, such as "PHP".

# Parameters

* `str` - String content.
* `persistent` - Whether the string should persist through the request
boundary.

# Panics

Panics under the following circumstances:

* The function used to create interned strings has not been set.
* The function could not allocate enough memory for the Zend string.

# Safety

When passing `persistent` as `false`, the caller must ensure that the
object does not attempt to live after the request finishes. When a
request starts and finishes in PHP, the Zend heap is deallocated and a
new one is created, which would leave a dangling pointer in the
[`ZBox`].

# Example

```no_run
use ext_php_rs::types::ZendStr;
use std::ffi::CString;

let c_s = CString::new("PHP").unwrap();
let s = ZendStr::interned_from_c_str(&c_s, true);
```
src/types/string.rs