'Returns a tuple of ``(ok, buffer, length)``.
The ``ok`` is i1 value that is set if ok.
The ``buffer`` is a i8* of the output buffer.
The ``length`` is a i32/i64 (py_ssize_t) of the length of the buffer.'

def string_as_string_and_size(self, strobj):

    p_length = cgutils.alloca_once(self.builder, self.py_ssize_t)
    if (PYVERSION >= (3, 0)):
        fnty = Type.function(self.cstring, [self.pyobj, self.py_ssize_t.as_pointer()])
        fname = 'PyUnicode_AsUTF8AndSize'
        fn = self._get_function(fnty, name=fname)
        buffer = self.builder.call(fn, [strobj, p_length])
        ok = self.builder.icmp_unsigned('!=', ir.Constant(buffer.type, None), buffer)
    else:
        fnty = Type.function(lc.Type.int(), [self.pyobj, self.cstring.as_pointer(), self.py_ssize_t.as_pointer()])
        fname = 'PyString_AsStringAndSize'
        fn = self._get_function(fnty, name=fname)
        p_buffer = cgutils.alloca_once(self.builder, self.cstring)
        status = self.builder.call(fn, [strobj, p_buffer, p_length])
        negone = ir.Constant(status.type, (-1))
        ok = self.builder.icmp_signed('!=', status, negone)
        buffer = self.builder.load(p_buffer)
    return (ok, buffer, self.builder.load(p_length))
