diff --git a/examples/socket/client.php b/examples/socket/client.php new file mode 100644 index 0000000..734ec23 --- /dev/null +++ b/examples/socket/client.php @@ -0,0 +1,22 @@ +socket($socket->AF_INET, $socket->SOCK_STREAM); +$client->connect(PyCore::tuple([HOST, PORT])); + +while (1) { + echo "> "; + $msg = trim(fgets(STDIN)); + if ($msg == 'quit') { + break; + } + $client->sendall(PyCore::bytes($msg)); + $data = $client->recv(1024); + if (empty($data)) { + break; + } + echo strval($data) . PHP_EOL; +} diff --git a/examples/socket/server.py b/examples/socket/server.py new file mode 100644 index 0000000..7664702 --- /dev/null +++ b/examples/socket/server.py @@ -0,0 +1,16 @@ +import socket + +HOST = "127.0.0.1" +PORT = 5432 + +with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.bind((HOST, PORT)) + s.listen() + conn, addr = s.accept() + with conn: + print(f"Connected by {addr}") + while True: + data = conn.recv(1024) + if not data: + break + conn.sendall(data) diff --git a/include/phpy.h b/include/phpy.h index e050c74..9c29895 100644 --- a/include/phpy.h +++ b/include/phpy.h @@ -375,6 +375,7 @@ PyObject *new_reference(zval *zv); PyObject *new_callable(zval *zv); const char *string2utf8(PyObject *pv, ssize_t *len); const char *string2char_ptr(PyObject *pv, ssize_t *len); +void string2zval(PyObject *pv, zval *zv); void tuple2argv(zval *argv, PyObject *args, ssize_t size, int begin = 1); void release_argv(uint32_t argc, zval *argv); } // namespace python diff --git a/src/bridge/core.cc b/src/bridge/core.cc index 97e7294..34168b0 100644 --- a/src/bridge/core.cc +++ b/src/bridge/core.cc @@ -481,6 +481,7 @@ namespace python { const char *string2utf8(PyObject *pv, ssize_t *len) { return PyUnicode_AsUTF8AndSize(pv, len); }; + const char *string2char_ptr(PyObject *pv, ssize_t *len) { const char *c_str; if (ZendString_Check(pv)) { @@ -500,6 +501,24 @@ const char *string2char_ptr(PyObject *pv, ssize_t *len) { } return c_str; } + +void string2zval(PyObject *pv, zval *zv) { + Py_ssize_t len; + auto sval = string2char_ptr(pv, &len); + if (sval != NULL) { + ZVAL_STRINGL(zv, sval, len); + return; + } + auto value = PyObject_Str(pv); + if (value != NULL) { + const char *sv = PyUnicode_AsUTF8AndSize(value, &len); + ZVAL_STRINGL(zv, sv, len); + Py_DECREF(value); + } else { + phpy::php::throw_error_if_occurred(); + } +} + void tuple2argv(zval *argv, PyObject *args, ssize_t size, int begin) { Py_ssize_t i; for (i = begin; i < size; i++) { diff --git a/src/php/object.cc b/src/php/object.cc index f55cbe8..c48f483 100644 --- a/src/php/object.cc +++ b/src/php/object.cc @@ -277,16 +277,7 @@ ZEND_METHOD(PyObject, __set) { } ZEND_METHOD(PyObject, __toString) { - auto object = phpy_object_get_handle(ZEND_THIS); - auto value = PyObject_Str(object); - if (value != NULL) { - Py_ssize_t sl; - const char *sv = PyUnicode_AsUTF8AndSize(value, &sl); - ZVAL_STRINGL(return_value, sv, sl); - Py_DECREF(value); - } else { - phpy::php::throw_error_if_occurred(); - } + phpy::python::string2zval(phpy_object_get_handle(ZEND_THIS), return_value); } ZEND_METHOD(PyObject, __invoke) { diff --git a/tests/phpunit/ObjectTest.php b/tests/phpunit/ObjectTest.php index f3ef83a..4179117 100644 --- a/tests/phpunit/ObjectTest.php +++ b/tests/phpunit/ObjectTest.php @@ -69,4 +69,11 @@ public function testIter() $data = iterator_to_array($fset); $this->assertEquals($data, $arr); } + + public function testBytes2Str() + { + $bytes = random_bytes(128); + $data = PyCore::bytes($bytes); + $this->assertEquals($bytes, strval($data)); + } }