{"id":337452,"date":"2022-08-23T21:00:30","date_gmt":"2022-08-23T21:00:30","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=337452"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=337452","title":{"rendered":"<span>\u0412\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c Lua \u0432 PHP \u0447\u0435\u0440\u0435\u0437 FFI<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><a href=\"https:\/\/www.php.net\/manual\/ru\/class.ffi.php\">Foreign Function Interface<\/a> \u2014 \u044d\u0442\u043e \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u043d\u0430\u044f \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 \u0434\u043b\u044f \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u0445 PHP-\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439.<\/p>\n<p>  <\/p>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c FFI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <a href=\"https:\/\/www.lua.org\/manual\/5.3\/\">liblua5<\/a> \u0438\u0437 PHP, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043d\u0430 Lua \u0438\u0437 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/xv\/em\/nl\/xvemnlq_kqrasv7-eqlz0uy4hdc.png\" data-src=\"https:\/\/habrastorage.org\/webt\/xv\/em\/nl\/xvemnlq_kqrasv7-eqlz0uy4hdc.png\"\/><\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<h2 id=\"motivaciya\">\u041c\u043e\u0442\u0438\u0432\u0430\u0446\u0438\u044f<\/h2>\n<p>  <\/p>\n<p>\u0414\u043b\u044f PHP \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 Lua \u0441 <a href=\"https:\/\/pecl.php.net\/package\/lua\">PECL<\/a>. \u0422\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u0441\u043c\u044b\u0441\u043b \u0432 \u043d\u0430\u0448\u0435\u0439 \u0437\u0430\u0434\u0443\u043c\u043a\u0435 \u0435\u0441\u0442\u044c:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u0427\u0435\u0440\u0435\u0437 FFI \u0435\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u043e\u043b\u043d\u043e\u043c\u0443 Lua API, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0443 \u043d\u0430\u0441 \u0431\u043e\u043b\u044c\u0448\u0435 \u0441\u0432\u043e\u0431\u043e\u0434\u044b.<\/li>\n<li>FFI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 Zend API, \u0438\u043c \u043f\u0440\u043e\u0449\u0435 \u043f\u0435\u0440\u0435\u0436\u0438\u0442\u044c \u043c\u0430\u0436\u043e\u0440\u043d\u044b\u0439 \u0440\u0435\u043b\u0438\u0437 PHP.<\/li>\n<li>\u0427\u0438\u0442\u0430\u0442\u044c PHP \u043a\u043e\u0434 \u043d\u0430\u043c \u043e\u0431\u044b\u0447\u043d\u043e \u043f\u0440\u043e\u0449\u0435, \u0447\u0435\u043c C \u0432 \u0441\u0432\u044f\u0437\u043a\u0435 \u0441 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u044f\u043c\u0438 PHP.<\/li>\n<li>\u041b\u0435\u0433\u0447\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043a\u0430\u043a composer \u043f\u0430\u043a\u0435\u0442, \u0432\u0435\u0434\u044c \u044d\u0442\u043e \u043e\u0431\u044b\u0447\u043d\u044b\u0439 PHP-\u043a\u043e\u0434.<\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u0415\u0449\u0451 \u043e\u0434\u043d\u0438\u043c \u0431\u043e\u043d\u0443\u0441\u043e\u043c FFI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u043e, \u0447\u0442\u043e \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u0438 \u043d\u0430 <a href=\"http:\/\/github.com\/VKCOM\/kphp\">KPHP<\/a>, \u0435\u0441\u043b\u0438 \u043c\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0440\u0430\u0441\u0441\u0442\u0430\u0432\u0438\u043c \u0442\u0438\u043f\u044b \u0447\u0435\u0440\u0435\u0437 phpdoc.<\/p>\n<p>  <\/p>\n<p>\u0421\u0435\u0439\u0447\u0430\u0441 \u043e\u0434\u0438\u043d \u0438\u0437 \u0433\u043b\u0430\u0432\u043d\u044b\u0445 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u043e\u0432 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u2014 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c. \u0418 \u0445\u043e\u0442\u044f \u0432 KPHP \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 FFI \u043d\u0435\u0441\u0451\u0442 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0435 \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b, \u0432 PHP \u0432\u0441\u0451 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0441\u043b\u043e\u0436\u043d\u0435\u0435. \u0410\u0432\u0442\u043e\u0440 JIT-\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0432 \u044f\u0434\u0440\u0435 PHP, <a href=\"https:\/\/github.com\/dstogov\">\u0414\u043c\u0438\u0442\u0440\u0438\u0439 \u0421\u0442\u043e\u0433\u043e\u0432<\/a>, \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442 \u0432 \u043e\u0442\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u043c \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u00ab\u043f\u043e\u0434\u0440\u0443\u0436\u0438\u0442\u044c\u00bb JIT \u0438 FFI, \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430.<\/p>\n<p>  <\/p>\n<blockquote><p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u0430\u043a\u0442\u0430: \u0414\u043c\u0438\u0442\u0440\u0438\u0439, \u043f\u043e\u043c\u0438\u043c\u043e \u043f\u0440\u043e\u0447\u0435\u0433\u043e, \u0435\u0449\u0451 \u0438 \u0430\u0432\u0442\u043e\u0440 FFI \u0434\u043b\u044f PHP.<\/p><\/blockquote>\n<p>\u041d\u043e \u0437\u0430\u0447\u0435\u043c \u0438\u043c\u0435\u043d\u043d\u043e liblua? \u0415\u0441\u0442\u044c \u0434\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u0440\u0438\u0447\u0438\u043d\u044b:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u042d\u0442\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u043b\u044f FFI. \u041f\u043e\u043b\u0435\u0437\u0435\u043d \u0432 \u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0446\u0435\u043b\u044f\u0445.<\/li>\n<li>\u0412 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c\u043e\u043c KPHP \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b.<\/li>\n<\/ol>\n<p>  <\/p>\n<h2 id=\"podgotovka-k-nachalu\">\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043a \u043d\u0430\u0447\u0430\u043b\u0443<\/h2>\n<p>  <\/p>\n<p>\u041d\u0430 \u0425\u0430\u0431\u0440\u0435 \u044f \u0443\u0436\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u043b, \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c composer-\u043f\u0430\u043a\u0435\u0442\u044b \u0434\u043b\u044f FFI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0441\u0440\u0430\u0437\u0443 \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043a \u0434\u0435\u043b\u0443. \u042f \u0431\u0443\u0434\u0443 \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u043a, \u0438\u0437\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 <a href=\"https:\/\/habr.com\/ru\/post\/653677\/\">\u00ab\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c SQLite \u0432 KPHP \u0438 PHP \u0447\u0435\u0440\u0435\u0437 FFI\u00bb<\/a>.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c liblua. \u041f\u043e\u0434\u043e\u0439\u0434\u0443\u0442 \u043b\u044e\u0431\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 5.1-5.4. \u0417\u0430\u0442\u0435\u043c \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u044d\u0442\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443. \u041d\u0430 Linux \u043d\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043c\u043e\u0447\u044c \u0443\u0442\u0438\u043b\u0438\u0442\u0430 <code>ldconfig<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\"># \u0417\u0430\u043f\u043e\u043c\u043d\u0438\u043c \u043f\u0443\u0442\u044c, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443, # \u043e\u043d \u043d\u0430\u043c \u0441\u043a\u043e\u0440\u043e \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f. $ ldconfig -p | grep lua     liblua5.3.so.0 (libc6,x86-64) => \/lib\/x86_64-linux\/liblua5.3.so.0<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430\u043c \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u043f\u043e\u043b\u0438\u0444\u0438\u043b\u044b \u0434\u043b\u044f KPHP:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ composer require vkcom\/kphp-polyfills<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"hello-world\">Hello, world!<\/h2>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Lua, \u043d\u0430\u0434\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c <a href=\"https:\/\/www.lua.org\/manual\/5.4\/manual.html#lua_State\"><code>lua_State<\/code><\/a>. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 <a href=\"https:\/\/www.lua.org\/manual\/5.3\/manual.html#luaL_newstate\"><code>luaL_newstate<\/code><\/a>.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043a\u0430\u043a\u043e\u0433\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u043a\u043e\u0434\u0430 \u043d\u0430 Lua \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0432\u0437\u044f\u0442\u044c <a href=\"https:\/\/www.lua.org\/manual\/5.3\/manual.html#luaL_dostring\"><code>luaL_dostring<\/code><\/a>, \u043d\u043e \u044d\u0442\u043e \u043c\u0430\u043a\u0440\u043e\u0441. \u041c\u0430\u043a\u0440\u043e\u0441\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0443 \u043d\u0430\u0441 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f, \u043d\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0434\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0435\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"cpp\">#define luaL_dostring(L, str) \\     (luaL_loadstring(L, str) || lua_pcall(L, 0, LUA_MULTRET, 0))  #define lua_pcall(L, n, r, f) \\     lua_pcallk(L, (n), (r), (f), 0, NULL)<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <a href=\"https:\/\/www.lua.org\/manual\/5.3\/manual.html#luaL_loadstring\"><code>luaL_loadstring<\/code><\/a> \u0438 <a href=\"https:\/\/www.lua.org\/manual\/5.3\/manual.html#lua_pcallk\"><code>lua_pcallk<\/code><\/a>.<\/p>\n<p>  <\/p>\n<p>\u0411\u0435\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u043e\u0432\u0430\u0442\u043e \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u043e\u0437\u044c\u043c\u0451\u043c \u0435\u0449\u0451 \u0438 <a href=\"https:\/\/www.lua.org\/manual\/5.4\/manual.html#luaL_openlibs\"><code>luaL_openlibs<\/code><\/a>.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0448 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0434\u043b\u044f FFI, <code>lua.h<\/code>, \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"cpp\">#define FFI_LIB \".\/ffilibs\/liblua5\" #define FFI_SCOPE \"lua\"  typedef struct lua_State lua_State; typedef intptr_t lua_KContext;  int luaL_loadstring(lua_State *L, const char *s);  int lua_pcallk(lua_State *L,                int nargs,                int nresults,                int errfunc,                lua_KContext ctx,                void *k);  lua_State *luaL_newstate();  void luaL_openlibs(lua_State *L);<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u043c liblua \u0442\u0430\u043c, \u0433\u0434\u0435 \u0435\u0433\u043e \u0441\u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u0439\u0442\u0438 \u043d\u0430\u0448\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ mkdir ffilibs $ cp \/lib\/x86_64-linux\/liblua5.3.so.0 ffilibs\/liblua5<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f PHP <a href=\"https:\/\/www.php.net\/manual\/ru\/ffi.load.php\"><code>FFI::load<\/code><\/a> \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 <a href=\"https:\/\/www.php.net\/manual\/ru\/ffi.scope.php\"><code>FFI::scope<\/code><\/a> \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 opcache preload. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 KPHP \u0443 \u043d\u0430\u0441 \u043d\u0435\u0442 opcache preload, \u043d\u043e <code>FFI::load<\/code> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u0431\u044b\u0441\u0442\u0440\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0433\u0434\u0435-\u0442\u043e \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430.<\/p>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u0432\u0430 \u0441\u043a\u0440\u0438\u043f\u0442\u0430: <code>main.php<\/code> \u0438 <code>preload.php<\/code>.<\/p>\n<p>  <\/p>\n<p><code>preload.php<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">&lt;?php  \/\/ \u0414\u043b\u044f PHP \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c load \u0432 preload-\u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435. FFI::load(__DIR__ . '\/lua.h');<\/code><\/pre>\n<p>  <\/p>\n<p><code>main.php<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">&lt;?php  require_once __DIR__ . '\/vendor\/autoload.php';  if (KPHP_COMPILER_VERSION) {     \/\/ \u0414\u043b\u044f KPHP \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c load \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430.     FFI::load(__DIR__ . '\/lua.h'); }  \/\/ \u0427\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u043b\u0430\u043a\u043e\u043d\u0438\u0447\u043d\u0435\u0435, \u043d\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0441\u0442\u0430\u0442\u0443\u0441\u044b \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u043d\u0438\u0436\u0435 \u0438 \u043d\u0435 \/\/ \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0438. $lib = FFI::scope('lua'); $state = $lib->luaL_newstate(); $lib->luaL_openlibs($state); $lib->luaL_loadstring($state, 'print(\"Hello, World!\")'); $lib->lua_pcallk($state, 0, 0, 0, 0, null);<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043d\u0430\u0448\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 \u0447\u0435\u0440\u0435\u0437 PHP:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ php -d opcache.enable_cli=1 \\       -d opcache.preload=preload.php \\       -f main.php Hello, World!<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430 KPHP:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ kphp --mode cli --composer-root $(pwd) main.php $ .\/kphp_out\/cli Hello, World!<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e! \u041c\u044b \u0443\u0436\u0435 \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 Lua-\u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b \u0432 \u043d\u0430\u0448\u0438\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430\u0445. \u0414\u0430\u043b\u044c\u0448\u0435 \u0431\u0443\u0434\u0435\u043c \u0434\u043e\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443, \u0434\u0435\u043b\u0430\u044f \u0435\u0451 \u0443\u0434\u043e\u0431\u043d\u0435\u0435, \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u0435\u0435 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u0435\u0435.<\/p>\n<p>  <\/p>\n<h2 id=\"allokator-pamyati\">\u0410\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u043f\u0430\u043c\u044f\u0442\u0438<\/h2>\n<p>  <\/p>\n<p>\u0415\u0441\u0442\u044c \u0434\u0432\u0430 \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u0441\u043e\u0437\u0434\u0430\u0442\u044c <code>lua_State<\/code>:<\/p>\n<p>  <\/p>\n<ul>\n<li><code>luaL_newstate<\/code> (\u0442\u043e, \u0447\u0442\u043e \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0440\u0430\u043d\u0435\u0435)<\/li>\n<li><code>lua_newstate<\/code><\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0421\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u0430 \u0443 <a href=\"https:\/\/www.lua.org\/manual\/5.4\/manual.html#lua_newstate\"><code>lua_newstate<\/code><\/a> \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u0430\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"cpp\">typedef void* (*lua_Alloc) (void *ud,                             void *ptr,                             size_t osize,                             size_t nsize);  lua_State *lua_newstate(lua_Alloc f, void *ud);<\/code><\/pre>\n<p>  <\/p>\n<p>\u0427\u0435\u0440\u0435\u0437 <code>lua_newstate<\/code> \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u043a\u0430\u043a \u0441\u0440\u0435\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f Lua \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0434\u0435\u043b\u044f\u0442\u044c \u0438 \u043e\u0447\u0438\u0449\u0430\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c. <code>luaL_newstate<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u0430\u043c\u044f\u0442\u044c\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0439 <code>realloc<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u0442\u044c \u043f\u0430\u0440\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u043e\u0432 \u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430. \u0415\u0441\u043b\u0438 \u0441\u043a\u0440\u0438\u043f\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u0438 \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u043a\u0440\u0430\u0449\u0435\u043d\u0430 \u0434\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f Lua-\u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0442\u0438 \u0443\u0442\u0435\u0447\u043a\u0430 \u043f\u0430\u043c\u044f\u0442\u0438. \u041f\u043e\u043c\u043e\u0447\u044c \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0437\u043e\u0432 <a href=\"https:\/\/www.lua.org\/manual\/5.4\/manual.html#lua_close\"><code>lua_close<\/code><\/a> \u0433\u0434\u0435-\u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0438 <a href=\"https:\/\/www.php.net\/manual\/en\/function.register-shutdown-function.php\">shutdown function<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0414\u0440\u0443\u0433\u043e\u0439 \u043c\u0438\u043d\u0443\u0441 \u2014 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u043b \u043f\u0430\u043c\u044f\u0442\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u0435\u0435 \u043f\u043e\u0434\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0451 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u043c.<\/p>\n<p>  <\/p>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0441\u0432\u043e\u0439 \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u043e \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u044f\u043c, \u0432\u044b\u0434\u0435\u043b\u044f\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432\u0443\u044e \u00ab\u043a\u0443\u0447\u0443\u00bb (\u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043e\u0447\u0438\u0449\u0435\u043d\u0430 \u043f\u043e\u0441\u043b\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430), \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u0438 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u043e\u0433\u043e Lua-\u0441\u043a\u0440\u0438\u043f\u0442\u0430.<\/p>\n<p>  <\/p>\n<p>\u042f \u043f\u043e\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u0447\u0435\u0440\u0435\u0437 FFI:<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">\/\/ \u041d\u0430\u0448 \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u044d\u043c\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 realloc. $state = $lib->lua_newstate(function ($ud, $ptr, $orig_size, $new_size) {     \/\/ \u0422\u0430\u043a \u043a\u0430\u043a \u0443 \u043d\u0430\u0441 \u043d\u0435\u0442 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0433\u043e FFI::realloc, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u0442\u044c     \/\/ \u0442\u0440\u0438 \u0441\u043b\u0443\u0447\u0430\u044f: \u043e\u0447\u0438\u0449\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u0438, \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430 \u0438     \/\/ \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 realloc (\u043a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043a\u0440\u0443\u043f\u043d\u044b\u0439 \u0431\u043b\u043e\u043a \u0438     \/\/ \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0443\u0434\u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0441\u0442\u0430\u0440\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430, \u043d\u0435 \u0437\u0430\u0431\u044b\u0432 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c     \/\/ \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u0442\u044c \u0440\u0430\u043d\u0435\u0435 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u0443\u044e \u043f\u0430\u043c\u044f\u0442\u044c).      if ($new_size === 0) {         if ($orig_size !== 0 &amp;&amp; $ptr !== null) {             \/\/ 1. free()             \\FFI::free(\\FFI::cast(\"uint8_t[$orig_size]\", $ptr));         }         return null;     }     if ($ptr === null) {         \/\/ 2. malloc()         $mem = \\FFI::new(\"uint8_t[$new_size]\", false);         return \\FFI::cast('void*', \\FFI::addr($mem));     }     \/\/ 3. realloc()     $copy_size = ($new_size > $orig_size) ? $orig_size : $new_size;     $mem = \\FFI::new(\"uint8_t[$new_size]\", false);     \\FFI::memcpy($mem, $ptr, $copy_size);     \\FFI::free(\\FFI::cast(\"uint8_t[$orig_size]\", $ptr));     return \\FFI::cast('void*', \\FFI::addr($mem)); }, null);<\/code><\/pre>\n<p>  <\/p>\n<p>\u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/www.php.net\/manual\/en\/ffi.new.php\"><code>FFI::new<\/code><\/a> \u0441 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c <code>$owned=false<\/code>, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c \u0432 C, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0432\u043b\u0430\u0434\u0435\u043d\u0438\u0435. \u0414\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0447\u0438\u0449\u0430\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c, \u043a\u043e\u0433\u0434\u0430 \u0441\u0447\u0451\u0442\u0447\u0438\u043a \u0435\u0433\u043e \u0441\u0441\u044b\u043b\u043e\u043a \u0434\u043e\u0441\u0442\u0438\u0433\u0430\u0435\u0442 \u043d\u0443\u043b\u044f.<\/p>\n<p>  <\/p>\n<p><a href=\"https:\/\/www.php.net\/manual\/ru\/ffi.free.php\"><code>FFI::free<\/code><\/a> \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u043e\u0447\u0438\u0449\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u044b\u0434\u0435\u043b\u044f\u043b\u0430\u0441\u044c \u0441 \u0444\u043b\u0430\u0433\u043e\u043c <code>$owned=false<\/code>. \u041f\u0430\u043c\u044f\u0442\u044c, \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u043b\u0430\u0434\u0435\u0435\u0442 PHP, \u043e\u0447\u0438\u0449\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 <code>FFI::free<\/code> \u043d\u0435\u043b\u044c\u0437\u044f.<\/p>\n<p>  <\/p>\n<p>\u0412 PHP FFI \u043d\u0435\u0442 \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 <code>realloc<\/code>, \u043d\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u044d\u043c\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044e \u0432\u044b\u0437\u043e\u0432\u043e\u0432 <code>FFI::new<\/code>, <a href=\"https:\/\/www.php.net\/manual\/ru\/ffi.memcpy.php\"><code>FFI::memcpy<\/code><\/a> \u0438 <code>FFI::free<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <a href=\"https:\/\/www.lua.org\/manual\/5.4\/manual.html#lua_Alloc\"><code>lua_Alloc<\/code><\/a> \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0443\u043c\u0435\u0441\u0442\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u0434\u0441\u0447\u0451\u0442 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 KPHP \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0441\u0432\u043e\u0435\u0433\u043e \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430 \u043c\u044b \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u043c \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u0438 \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/github.com\/VKCOM\/ktest\">ktest<\/a>-\u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0438. \u041d\u043e \u043a \u043d\u0438\u043c \u043c\u044b \u0432\u0435\u0440\u043d\u0451\u043c\u0441\u044f \u043f\u043e\u0437\u0434\u043d\u0435\u0435.<\/p>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u044f \u0431\u0443\u0434\u0443 \u0441\u0447\u0438\u0442\u0430\u0442\u044c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043a\u043b\u0430\u0441\u0441 <code>MyLua<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 <code>$lib<\/code> \u0438 <code>$state<\/code>. \u0412 \u043d\u0435\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0432\u0441\u044e \u043d\u043e\u0432\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">class MyLua {     \/** @var ffi_scope&lt;lua> *\/     public static $lib;      \/** @var ffi_cdata&lt;lua, struct lua_State*> *\/     public static $state = null;      public static function eval(string $code) {         \/\/ \u041a\u043e\u0434, \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0432\u044b\u0432\u043e\u0434\u0438\u043b\u0438 hello world.     } }<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"predosterezheniya-pri-rabote-s-ffifree\">\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0435\u0440\u0435\u0436\u0435\u043d\u0438\u044f \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 FFI::free<\/h2>\n<p>  <\/p>\n<p>\u0415\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0437\u0430\u0432\u0430\u043b\u0438\u0442\u044c PHP (\u0438 KPHP) \u0432 segfault \u0447\u0435\u0440\u0435\u0437 <code>FFI::free<\/code>. \u041a\u0440\u043e\u043c\u0435 \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u043f\u0440\u0430\u0432\u0438\u043b, \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0445 \u043d\u0430\u043c \u0435\u0449\u0451 \u0438\u0437 C, \u0435\u0441\u0442\u044c \u043c\u0435\u043d\u0435\u0435 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0435 \u043d\u044e\u0430\u043d\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043b\u0435\u0433\u043a\u043e \u043f\u0440\u043e\u0433\u043b\u044f\u0434\u0435\u0442\u044c.<\/p>\n<p>  <\/p>\n<p>\u042f \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432, \u043a\u0430\u043a \u0434\u0435\u043b\u0430\u0442\u044c \u0442\u043e\u0447\u043d\u043e \u043d\u0435 \u0441\u0442\u043e\u0438\u0442.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">\/\/ \u041f\u041b\u041e\u0425\u041e: \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c free() \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043a \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0443 FFI::addr() $obj = FFI::new('uint64_t', false); FFI::free(FFI::addr($obj));  \/\/ \u0425\u041e\u0420\u041e\u0428\u041e: \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c free() \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043a \u0441\u0430\u043c\u043e\u043c\u0443 CData-\u043e\u0431\u044a\u0435\u043a\u0442\u0443 $obj = FFI::new('uint64_t', false); FFI::free($obj);<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"php\">\/\/ \u041f\u041b\u041e\u0425\u041e: \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u043a void* \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f addr() $obj = FFI::new(\"int[$size]\", false); $ptr = FFI::cast('void*', $obj); FFI::free($ptr);  \/\/ \u0425\u041e\u0420\u041e\u0428\u041e: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c addr() \u043f\u0440\u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u043a \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044e $obj = FFI::new(\"int[$size]\", false); $ptr = FFI::cast('void*', FFI::addr($obj)); FFI::free($ptr);<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"php\">\/\/ \u041f\u041b\u041e\u0425\u041e: \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0430\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430 $arr = FFI::new('int[10]', false); $arr_ptr = FFI::cast('void*', FFI::addr($arr)); $arr2 = FFI::cast('int[5]', $arr_ptr); FFI::free($arr2);  \/\/ \u0425\u041e\u0420\u041e\u0428\u041e: \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0430\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u043c \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c $arr = FFI::new('int[10]', false); $arr_ptr = FFI::cast('void*', FFI::addr($arr)); $arr2 = FFI::cast('int[10]', $arr_ptr); FFI::free($arr2);<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"konvertaciya-znacheniy-iz-php-v-lua\">\u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0438\u0437 PHP \u0432 Lua<\/h2>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432 Lua \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043e\u0441\u043c\u044b\u0441\u043b\u0435\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c PHP-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442\u044b Lua. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0438\u0448\u0435\u043c \u043c\u0435\u0442\u043e\u0434 <code>MyLua::php2lua<\/code>. \u041e\u043d \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434 <code>mixed<\/code> \u0438 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 Lua-\u0441\u0442\u0435\u043a.<\/p>\n<p>  <\/p>\n<p>\u0412\u043e\u0442 \u0442\u0430\u0431\u043b\u0438\u0446\u0430 PHP-\u0442\u0438\u043f\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c, \u0430 \u0442\u0430\u043a\u0436\u0435 Lua-\u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u044d\u0442\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0441\u0442\u0435\u043a\u0435:<\/p>\n<p>  <\/p>\n<div class=\"scrollable-table\">\n<table>\n<thead>\n<tr>\n<th>PHP-\u0442\u0438\u043f<\/th>\n<th>Lua C API<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>null<\/td>\n<td><a href=\"https:\/\/www.lua.org\/manual\/5.4\/manual.html#lua_pushnil\"><code>lua_pushnil<\/code><\/a><\/td>\n<\/tr>\n<tr>\n<td>bool<\/td>\n<td><a href=\"https:\/\/www.lua.org\/manual\/5.4\/manual.html#lua_pushboolean\"><code>lua_pushboolean<\/code><\/a><\/td>\n<\/tr>\n<tr>\n<td>int, float<\/td>\n<td><a href=\"https:\/\/www.lua.org\/manual\/5.4\/manual.html#lua_pushnumber\"><code>lua_pushnumber<\/code><\/a><\/td>\n<\/tr>\n<tr>\n<td>string<\/td>\n<td><a href=\"https:\/\/www.lua.org\/manual\/5.4\/manual.html#lua_pushlstring\"><code>lua_pushlstring<\/code><\/a><\/td>\n<\/tr>\n<tr>\n<td>array<\/td>\n<td><a href=\"https:\/\/www.lua.org\/manual\/5.4\/manual.html#lua_createtable\"><code>lua_createtable<\/code><\/a>, <a href=\"https:\/\/www.lua.org\/manual\/5.4\/manual.html#lua_rawset\"><code>lua_rawset<\/code><\/a>, <a href=\"https:\/\/www.lua.org\/manual\/5.4\/manual.html#lua_rawseti\"><code>lua_rawseti<\/code><\/a><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>  <\/p>\n<p>\u0412 \u043d\u0430\u0448 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u044b\u0439 \u0444\u0430\u0439\u043b <code>lua.h<\/code> \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u044b\u0448\u0435\u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"cpp\">typedef double lua_Number; typedef int64_t lua_Integer;  void lua_pushnil(lua_State *L); void lua_pushboolean(lua_State *L, int b); void lua_pushnumber(lua_State *L, lua_Number n); const char *lua_pushlstring(lua_State *L, const char *s, size_t len);  void lua_createtable(lua_State *L, int narr, int nrec); void lua_rawset(lua_State *L, int index); void lua_rawseti(lua_State *L, int index, lua_Integer i);<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u0430\u043a\u0446\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043d\u043e\u0432\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 <code>lua.h<\/code>. \u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0432\u0441\u0435\u0433\u0434\u0430 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u044b\u0439: \u0435\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0438\u0437 PHP, \u0442\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u0435\u0451 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u0443 \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u044b\u0439 \u0444\u0430\u0439\u043b.<\/p>\n<p>  <\/p>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u043d\u0430\u0431\u0440\u043e\u0441\u043e\u043a <code>php2lua<\/code> \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">public static function php2lua($value) {     if (is_string($value)) {         self::$lib->lua_pushlstring(self::$state, $value, strlen($value));     } else if (is_int($value) || is_float($value)) {         self::$lib->lua_pushnumber(self::$state, (float)$value);     } else if (is_bool($value)) {         self::$lib->lua_pushboolean(self::$state, (int)$value);     } else if (is_array($value)) {         \/\/ TODO: \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u043d\u0438\u0436\u0435.     } else {         \/\/ \u041a\u0430\u043a\u0438\u0435-\u0442\u043e \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f (\u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 null),         \/\/ \u0431\u0443\u0434\u0435\u043c \u043f\u0443\u0448\u0438\u0442\u044c \u043a\u0430\u043a nil; \u044d\u0442\u043e \u043d\u0435 \u0441\u0430\u043c\u043e\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435,         \/\/ \u043d\u043e \u043e\u043d\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0435\u0435, \u0447\u0435\u043c \u043a\u0438\u0434\u0430\u0442\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 (\u0447\u0438\u0442\u0430\u0439\u0442\u0435 \u043d\u0438\u0436\u0435).         self::$lib->lua_pushnil(self::$state);     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0441\u0442\u043e\u0438\u0442 \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u044d\u0442\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0441\u043e \u0441\u0442\u0435\u043a\u043e\u043c Lua, \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u044b\u043c\u0438 \u0438 \u043d\u0435 \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0435\u0433\u043e \u0432 \u043d\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438. \u0415\u0441\u043b\u0438 \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0432\u044b\u0437\u043e\u0432\u0430 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043c\u044b \u043d\u0435 \u0441\u043c\u043e\u0433\u043b\u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u0437 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0442\u043e \u0432\u0441\u0435 \u0443\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0432 \u0441\u0442\u0435\u043a \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0443\u0434\u0430\u043b\u0435\u043d\u044b. \u0422\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0432\u0435\u0440\u043d\u043e \u0438 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u043e. \u041f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u0432\u0435\u0440\u0445\u043d\u0435\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0435 (\u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435) \u043c\u0435\u0442\u043e\u0434\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u044e\u0442 \u0441\u0442\u0435\u043a \u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442 \u0435\u0433\u043e \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435. \u0427\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e, \u043d\u0443\u0436\u043d\u043e \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0435\u0441\u0441\u0438\u043c\u0438\u0441\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0433\u043b\u0443\u0431\u0438\u043d\u0443 \u0441\u0442\u0435\u043a\u0430 \u043f\u0435\u0440\u0435\u0434 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c \u043b\u043e\u0433\u0438\u043a\u0438 \u043c\u0435\u0442\u043e\u0434\u0430, \u0447\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043b\u0438\u0448\u043d\u0438\u0435 \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b.<\/p>\n<p>  <\/p>\n<p>\u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c PHP-\u043c\u0430\u0441\u0441\u0438\u0432 \u0432 Lua-\u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u2014 \u0441 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u043f\u043e\u043d\u044f\u0442\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430. \u041a\u0430\u0436\u0434\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437 <code>php2lua<\/code>. \u0410 \u0441 \u0434\u0440\u0443\u0433\u043e\u0439, \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0443\u043c\u0435\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c <a href=\"https:\/\/www.lua.org\/pil\/11.1.html\">sequence-like \u0442\u0430\u0431\u043b\u0438\u0446\u044b<\/a> \u0434\u043b\u044f Lua, \u0435\u0441\u043b\u0438 \u0432 PHP \u043c\u0430\u0441\u0441\u0438\u0432 \u0431\u044b\u043b \u0431\u0435\u0437 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043e\u0432.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">if (array_is_list($value)) {     self::$lib->lua_createtable(self::$state, count($value), 0);     $table_index = 1; \/\/ \u0412 Lua \"\u043c\u0430\u0441\u0441\u0438\u0432\u0430\u0445\" \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442\u0441\u044f \u0441 1     foreach ($value as $elem) {         self::php2lua($elem);         self::$lib->lua_rawseti(self::$state, -2, $table_index);         $table_index++;     }     return; } \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u044f\u043c\u043e\u043b\u0438\u043d\u0435\u0439\u043d\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c. self::$lib->lua_createtable(self::$state, 0, 0); foreach ($value as $key => $elem) {     self::php2lua($key);     self::php2lua($elem);     self::$lib->lua_rawset(self::$state, -3); }<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"konvertaciya-znacheniy-iz-lua-v-php\">\u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0438\u0437 Lua \u0432 PHP<\/h2>\n<p>  <\/p>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>MyLua::lua2php<\/code> \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e, \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e <code>MyLua::php2lua<\/code>. <code>lua2php<\/code> \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434 \u0438\u043d\u0434\u0435\u043a\u0441 \u0432\u043d\u0443\u0442\u0440\u0438 Lua-\u0441\u0442\u0435\u043a\u0430 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u044d\u0442\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0432 \u0438\u0445 \u0432 PHP-\u0444\u043e\u0440\u043c\u0430\u0442. \u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043d\u0435 \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0438\u0437 \u0441\u0442\u0435\u043a\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443, \u0435\u0441\u043b\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0442\u0438\u043f\u0430 <code>pop()<\/code>, \u043d\u0443\u0436\u043d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0430 \u0437\u0430\u0442\u0435\u043c \u0443\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c <code>stackDiscard(1)<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">\/**  * @param int $n  *\/ public static function stackDiscard($n) {     \/\/ lua_pop - \u044d\u0442\u043e \u043c\u0430\u043a\u0440\u043e\u0441, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c lua_settop.     self::$lib->lua_settop(self::$state, -($n) - 1); }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u0437\u0430 \u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043f\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0443, \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u0442\u0435\u0433\u043e\u0432 \u0442\u0438\u043f\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">public const TNIL = 0; public const TBOOLEAN = 1; public const TLIGHTUSERDATA = 2; public const TNUMBER = 3; public const TSTRING = 4; public const TTABLE = 5; public const TFUNCTION = 6; public const TUSERDATA = 7; public const TTHREAD = 8;<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"php\">\/**  * @param int $index  * @return mixed  *\/ public static function lua2php($index) {     switch (self::$lib->lua_type(self::$state, $index)) {     case self::TNIL:         return null;     case self::TBOOLEAN:         return (bool)self::$lib->lua_toboolean(self::$state, $index);     case self::TNUMBER:         return self::$lib->lua_tonumberx(self::$state, $index, null);     case self::TSTRING:         return self::$lib->lua_tolstring(self::$state, $index, null);     case self::TTABLE:         return self::lua2phpTable($index);     default:         return ['_error' => \"unsupported Lua->PHP type\"];     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u0431\u043b\u0438\u0446\u044b \u0431\u0443\u0434\u0435\u043c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043a\u0430\u043a \u0435\u0441\u0442\u044c, \u0431\u0435\u0437 \u043f\u043e\u043f\u044b\u0442\u043e\u043a \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0442\u044c \u0442\u0430\u043c sequence\/array table.<\/p>\n<p>  <\/p>\n<blockquote><p>\u0412 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 <a href=\"https:\/\/github.com\/quasilyte\/KLua\">KLua<\/a> \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c <code>{\"a\", \"b\"}<\/code> \u0432 <code>[\"a\", \"b\"]<\/code> \u0432\u043c\u0435\u0441\u0442\u043e <code>[1 => \"a\", 2 => \"b\"]<\/code>. \u041d\u043e \u044d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0441 \u044d\u0432\u0440\u0438\u0441\u0442\u0438\u043a\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p><\/blockquote>\n<p>  <\/p>\n<pre><code class=\"php\">\/**  * @param int $index  * @return mixed[]  *\/ public static function lua2phpTable($index) {     $result = [];     \/\/ \u041a\u043b\u0430\u0434\u0451\u043c \u043d\u0430 \u0441\u0442\u0435\u043a \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u043b\u044e\u0447 - nil.     self::$lib->lua_pushnil(self::$state);     while (self::$lib->lua_next(self::$state, $index) !== 0) {         $value = self::lua2php(-1);         self::stackDiscard(1);         $result[self::lua2php(-1)] = $value;         \/\/ \u0412\u0435\u0440\u0445\u0443\u0448\u043a\u0430 \u0441\u0442\u0435\u043a\u0430 (\u043a\u043b\u044e\u0447) \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0434\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438.     }     return $result; }<\/code><\/pre>\n<p>  <\/p>\n<p><code>lua2php<\/code> \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u0432 \u0434\u0432\u0443\u0445 \u043c\u0435\u0441\u0442\u0430\u0445:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0414\u043b\u044f \u043c\u0435\u0442\u043e\u0434\u0430 <code>MyLua::call<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0441\u043a\u043e\u0440\u043e \u043d\u0430\u043f\u0438\u0448\u0435\u043c.<\/li>\n<li>\u0414\u043b\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0438\u0437 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 <code>MyLua::eval<\/code>.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412 \u043c\u0435\u0442\u043e\u0434\u0430\u0445 \u0442\u0438\u043f\u0430 <code>MyLua::getGlobalVar<\/code> \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u043b\u0430\u0441\u044c \u0431\u044b \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u044f.<\/p>\n<p>  <\/p>\n<h2 id=\"soedinyaem-dva-mira\">\u0421\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u043c \u0434\u0432\u0430 \u043c\u0438\u0440\u0430<\/h2>\n<p>  <\/p>\n<p>\u041c\u044b \u0443\u043c\u0435\u0435\u043c \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043e\u0431\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u044b. \u042d\u0442\u043e \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0438\u0437 PHP \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0430 Lua, \u043f\u043e\u043b\u0443\u0447\u0430\u044f \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0442\u043e\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438\u0437 PHP.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0432\u044b\u0437\u043e\u0432\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u041a\u043b\u0430\u0434\u0451\u043c Lua-\u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043d\u0430 \u0441\u0442\u0435\u043a.<\/li>\n<li>\u041f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0435\u043c \u0432\u0441\u0435 PHP-\u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0432 \u0441\u0442\u0435\u043a \u0447\u0435\u0440\u0435\u0437 <code>php2lua<\/code>.<\/li>\n<li>\u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c Lua-\u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 <code>lua_pcallk<\/code>.<\/li>\n<li>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0437\u0430\u0431\u0438\u0440\u0430\u0435\u043c \u0441\u043e \u0441\u0442\u0435\u043a\u0430 \u0447\u0435\u0440\u0435\u0437 <code>lua2php<\/code>.<\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u0412\u044b\u0437\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u0437 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043b\u0438\u0448\u044c \u0442\u0435\u043c, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0432 \u0441\u0442\u0435\u043a \u0442\u0430\u0431\u043b\u0438\u0446\u0443, \u0430 \u043f\u043e\u0442\u043e\u043c \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u0438\u0437 \u043d\u0435\u0451 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043f\u043e \u043d\u0443\u0436\u043d\u043e\u043c\u0443 \u043a\u043b\u044e\u0447\u0443.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">\/**  * @param string $func_name  * @param int $num_results  * @param mixed[] $args  *\/ public static function call($func_name, $num_results, ...$args) {     $type = self::$lib->lua_getglobal(self::$state, $func_name);     if ($type !== self::TFUNCTION) {         self::stackDiscard(1); \/\/ \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 $func_name.         throw new \\Exception(\"can't find $func_name function\");     }     foreach ($args as $arg) {         self::php2lua($arg);     }     $status = self::$lib->lua_pcallk(self::$state,         count($args), $num_results,         0, 0, null);     if ($status) {         \/\/ Lua \u043a\u043b\u0430\u0434\u0451\u0442 \u043e\u0448\u0438\u0431\u043a\u0443 \u043d\u0430 \u0441\u0442\u0435\u043a.         $err = self::lua2php(-1);         self::stackDiscard(1);         throw new \\Exception(\"$func_name: $err\");     }     return self::collectCallResults($num_results); }  public static function collectCallResults($num_results) {     switch ($num_results) {         case 0:             return null;         case 1:             $result = self::lua2php(-1);             self::stackDiscard(1);             return $result;         default:             \/\/ \u0417\u0434\u0435\u0441\u044c \u043b\u0438\u0431\u043e \u0446\u0438\u043a\u043b \u0441 lua2php \u0441 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0432 \u043c\u0430\u0441\u0441\u0438\u0432,             \/\/ \u043b\u0438\u0431\u043e \u0431\u043e\u043b\u0435\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0441 \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u0446\u0438\u0435\u0439 \u0441\u0442\u0435\u043a\u0430.     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u0441\u043c\u043e\u0436\u0435\u043c \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">$result = MyLua::call('type', 1, 43.5); var_dump($result); \/\/ \"number\"<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"avtomaticheskiy-podschyot-num_results\">\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043e\u0434\u0441\u0447\u0451\u0442 $num_results<\/h2>\n<p>  <\/p>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e. \u041a \u0442\u043e\u043c\u0443 \u0436\u0435 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043c\u043e\u0433\u0443\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432. \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0443\u043c\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0438 \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u044f\u0432\u043d\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <code>$num_results<\/code>.<\/p>\n<p>  <\/p>\n<p>\u041c\u0435\u043d\u044f\u0435\u043c \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u0443:<\/p>\n<p>  <\/p>\n<pre><code class=\"diff\">- public static function call($func_name, $num_results, ...$args) { + public static function call($func_name, ...$args) {<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043d\u0430 \u0441\u0442\u0435\u043a, \u0437\u0430\u043f\u0438\u0448\u0435\u043c \u0435\u0433\u043e \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0433\u043b\u0443\u0431\u0438\u043d\u0443:<\/p>\n<p>  <\/p>\n<pre><code class=\"diff\">+ $stack_top = self::$lib->lua_gettop(self::$state);   $type = self::$lib->lua_getglobal(self::$state, $func_name);<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 <code>lua_pcallk<\/code> \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c <code>MULTRET<\/code> (-1) \u0432\u043c\u0435\u0441\u0442\u043e <code>$num_results<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"diff\">  $status = self::$lib->lua_pcallk(self::$state, -     count($args), $num_results, +     count($args), -1,       0, 0, null);<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 <code>lua_pcallk<\/code> \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432:<\/p>\n<p>  <\/p>\n<pre><code class=\"diff\">+ $num_results = self::$lib->lua_gettop(self::$state) - $stack_top;   return self::collectCallResults($num_results);<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"vyzyvaem-php-iz-lua\">\u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c PHP \u0438\u0437 Lua<\/h2>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432\u044b\u0437\u0432\u0430\u0442\u044c PHP-\u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0438\u0437 Lua, \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0435\u0451 \u043a\u0430\u043a <a href=\"https:\/\/www.lua.org\/manual\/5.3\/manual.html#lua_CFunction\"><code>lua_CFunction<\/code><\/a> \u0432 <a href=\"https:\/\/www.lua.org\/manual\/5.3\/manual.html#lua_pushcclosure\"><code>lua_pushcclosure<\/code><\/a> \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0433\u0434\u0435-\u043d\u0438\u0431\u0443\u0434\u044c (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439). \u042d\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u0437 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e C-\u043a\u043e\u0434, \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439 Lua-\u0441\u043a\u0440\u0438\u043f\u0442\u044b.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0432 \u0442\u0430\u043a\u043e\u043c \u0432\u043d\u0435\u0448\u043d\u0435\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u0437\u0430\u043f\u0440\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u043a\u0438\u0434\u0430\u0442\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f. \u0412 PHP \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u043e\u0439 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0430 \u0432 KPHP \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f. KPHP \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435: \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438 \u043b\u044f\u043c\u0431\u0434\u044b \u0431\u0435\u0437 \u0437\u0430\u043c\u044b\u043a\u0430\u0435\u043c\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445.<\/p>\n<p>  <\/p>\n<p><code>lua_CFunction<\/code> \u2014 \u044d\u0442\u043e \u043d\u0438\u0437\u043a\u0438\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438. \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0432\u044b\u0437\u043e\u0432\u0430 \u043c\u044b \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0438\u0437 \u0441\u0442\u0435\u043a\u0430 \u0441\u0430\u043c\u0438, \u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043a\u043b\u0430\u0434\u0451\u043c \u0432 \u0441\u0442\u0435\u043a. \u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u0438 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0431\u0451\u0440\u0442\u043a\u0438 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 PHP-\u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0445\u043e\u0442\u0438\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c\u0438 \u0432 Lua. \u041e\u0431\u0451\u0440\u0442\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u0417\u0430\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u043e \u0441\u0442\u0435\u043a\u0430 \u043d\u0443\u0436\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 <code>lua2php<\/code>.<\/li>\n<li>\u0412\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e PHP-\u0444\u0443\u043d\u043a\u0446\u0438\u044e.<\/li>\n<li>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0451\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 <code>php2lua<\/code> (\u043e\u043d\u043e \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u043d\u0430 \u0441\u0442\u0435\u043a).<\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0433\u043e API \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u044f \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438.<\/p>\n<p>  <\/p>\n<p>\u042f \u043f\u043e\u043a\u0430\u0436\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0434\u043b\u044f PHP \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0441 \u0434\u0432\u0443\u043c\u044f \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438, \u043d\u043e \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0445\u043e\u0436\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0434\u043b\u044f \u0443\u0447\u0451\u0442\u0430 \u0440\u0430\u0437\u043d\u043e\u0439 \u0430\u0440\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>  <\/p>\n<p>\u0412\u043e\u0442 \u043f\u0435\u0440\u0432\u0430\u044f \u043f\u043e\u043f\u044b\u0442\u043a\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">\/**  * @param string $func_name  * @param callable(mixed,mixed):mixed $fn  *\/ public static function registerFunction2($func_name, $fn) {     self::$lib->lua_pushcclosure(self::$state, function ($s) use ($fn) {         \/\/ 1. \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0438 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b.         $arg1 = self::lua2php(1);         $arg2 = self::lua2php(2);         \/\/ 2. \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e.         $result = $fn($arg1, $arg2);         \/\/ 3. \u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.         self::php2lua($result);         return 1;     }, 0);     \/\/ \u041f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e Lua \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439.     self::$lib->lua_setglobal(self::$state, $func_name); }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0432 KPHP \u043d\u0435\u043b\u044c\u0437\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>$fn<\/code> \u0438\u0437 \u0442\u0435\u043b\u0430 \u043b\u044f\u043c\u0431\u0434\u044b: \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434 \u043d\u0435 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f. \u0410 \u043a \u0447\u0435\u043c\u0443 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u0438\u0437 \u044d\u0442\u043e\u0439 \u043b\u044f\u043c\u0431\u0434\u044b? \u041a \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e, \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u043a \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u043f\u043e\u043b\u044f\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u0432. \u042d\u0442\u0438\u043c \u0438 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 <code>MyLua<\/code> \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u043b\u044f\u043c\u0431\u0434.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">\/** @var (callable(mixed,mixed):mixed)[] *\/ public static $phpfuncs2 = [];<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u0435\u043c \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>registerFunction2<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"diff\">+ $id = count(self::$phpfuncs2); + self::$phpfuncs2[] = $fn;  - self::$lib->lua_pushcclosure(self::$state, function ($s) use ($fn) { + self::$lib->lua_pushcclosure(self::$state, function ($s) {       \/\/ 1. \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0438 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b.       $arg1 = self::lua2php(1);       $arg2 = self::lua2php(2);       \/\/ 2. \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e. +     $fn = self::$phpfuncs2[$id];       $result = $fn($arg1, $arg2);       \/\/ 3. \u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.       self::php2lua($result);       return 1;   }, 0);<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u043e \u043f\u043e\u0434\u043e\u0436\u0434\u0438\u0442\u0435, \u0430 \u043a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 <code>$id<\/code>, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0439\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435? \u041d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0434\u0443\u0442 <a href=\"https:\/\/www.lua.org\/pil\/27.3.3.html\">upvalues<\/a> \u0438\u0437 Lua API. \u041f\u0440\u0430\u0432\u0434\u0430, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0438\u043c\u0438 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u0438\u0442 \u0440\u0435\u0448\u0438\u0442\u044c \u0437\u0430\u0433\u0430\u0434\u043a\u0443. \u0412\u043e\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 <code>lua_upvalueindex<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"cpp\">#if LUAI_BITSINT >= 32 #  define LUAI_MAXSTACK 1000000 #else #  define LUAI_MAXSTACK 15000 #endif  #define LUA_REGISTRYINDEX   (-LUAI_MAXSTACK - 1000) #define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i))<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043c\u0430\u043a\u0440\u043e\u0441, \u0432\u0435\u0434\u044c \u043e\u043d \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u043f\u0440\u0435\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430. \u0410 \u0442\u0430, \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0432\u043e\u043e\u0431\u0449\u0435 \u043c\u043e\u0436\u0435\u0442 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0441\u0431\u043e\u0440\u043a\u0435 liblua.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u0442 \u0440\u0430\u0437 \u043a\u0440\u0430\u0441\u0438\u0432\u043e \u0440\u0435\u0448\u0438\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f. \u041b\u0443\u0447\u0448\u0435\u0435, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u044d\u0442\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0434\u043b\u044f <code>LUAI_MAXSTACK<\/code> \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0434\u043b\u044f 64-\u0431\u0438\u0442\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0435\u0433\u043e, \u0435\u0441\u043b\u0438 liblua \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043b\u0441\u044f \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">\/**  * @param int $i  *\/ public static function upvalueIndex($i) {     \/\/ $lua_max_stack - \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0443\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435,     \/\/ \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0440\u0430\u0432\u043d\u043e 1000000.     $registry_index = (-self::$lua_max_stack - 1000);     return $registry_index - $i; }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043b\u043e\u0436\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043f\u043e\u0437\u0430\u0434\u0438. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 <code>registerFunction2<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">\/**  * @param string $func_name  * @param callable(mixed,mixed):mixed $fn  *\/ public static function registerFunction2($func_name, $fn) {     \/\/ \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c PHP-\u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f.     \/\/ $id \u0432\u044b\u0434\u0430\u0451\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435.     $id = count(self::$phpfuncs2);     self::$phpfuncs2[] = $fn;      \/\/ \u041a\u043b\u0430\u0434\u0451\u043c $id \u043d\u0430 \u0441\u0442\u0435\u043a, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u043a\u0430\u043a upvalue.     self::$lib->lua_pushnumber(self::$state, (float)$id);     self::$lib->lua_pushcclosure(self::$state, function ($s) {         \/\/ 1. \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0438 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b.         $arg1 = self::lua2php(1);         $arg2 = self::lua2php(2);         \/\/ 2. \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e.         $up_index = self::upvalueIndex(1);         $id = (int)self::$lib->lua_tonumberx($s, $up_index, null);         $fn = self::$phpfuncs2[$id];         $result = $fn($arg1, $arg2);         \/\/ 3. \u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.         self::php2lua($result);         return 1;     }, 1); \/\/ \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435: \u0442\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 1 upvalue, \u0430 \u043d\u0435 0.      \/\/ \u041f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e Lua-\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439.     self::$lib->lua_setglobal(self::$state, $func_name); }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u044d\u0442\u043e \u0432\u0441\u0451 \u0432 \u0434\u0435\u043b\u0435!<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">MyLua::registerFunction2('phpconcat', function ($s1, $s2) {     return $s1 . $s2; });  $result = MyLua::call('phpconcat', 'a', 'b'); var_dump($result); \/\/ \"ab\"<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0447\u0442\u043e \u0434\u0430\u0436\u0435 \u043d\u0435 \u0437\u0430\u0434\u0443\u043c\u044b\u0432\u0430\u0435\u0448\u044c\u0441\u044f \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u043e\u0439 \u043f\u0443\u0442\u044c \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u043b\u0438 \u0441\u0442\u0440\u043e\u0447\u043a\u0438 <code>\"a\"<\/code> \u0438 <code>\"b\"<\/code>, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043c\u044b \u0440\u0430\u0441\u043f\u0435\u0447\u0430\u0442\u0430\u043b\u0438 \u0438\u0445 \u0432\u043c\u0435\u0441\u0442\u0435 \u043a\u0430\u043a <code>\"ab\"<\/code>.<\/p>\n<p>  <\/p>\n<ol>\n<li>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043b\u0438 PHP-\u0441\u0442\u0440\u043e\u043a\u0438 \u0432 Lua-\u0441\u0442\u0440\u043e\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 <code>php2lua<\/code>.<\/li>\n<li>\u0417\u0430\u0442\u0435\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b <code>phpconcat<\/code> \u0438\u0437 Lua-\u0441\u0442\u0440\u043e\u043a \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u043b\u0438\u0441\u044c \u0432 PHP-\u0441\u0442\u0440\u043e\u043a\u0438.<\/li>\n<li>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>phpconcat<\/code> \u043f\u0440\u0438\u043d\u044f\u043b\u0430 PHP-\u0441\u0442\u0440\u043e\u043a\u0443 \u0438 \u0432\u0435\u0440\u043d\u0443\u043b\u0430 PHP-\u0441\u0442\u0440\u043e\u043a\u0443.<\/li>\n<li>\u041d\u0430\u0448\u0430 \u043e\u0431\u0451\u0440\u0442\u043a\u0430 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043b\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0438\u0437 PHP-\u0441\u0442\u0440\u043e\u043a\u0438 \u0432 Lua-\u0441\u0442\u0440\u043e\u043a\u0443.<\/li>\n<li>\u0418 \u0432 \u0441\u0430\u043c\u043e\u043c \u043a\u043e\u043d\u0446\u0435 <code>MyLua::call<\/code> \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043b\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432 PHP-\u0441\u0442\u0440\u043e\u043a\u0443.<\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u0412\u044b\u0437\u044b\u0432\u0430\u0442\u044c PHP-\u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 <code>MyLua::call<\/code> \u0441\u043c\u044b\u0441\u043b\u0430 \u043e\u0441\u043e\u0431\u043e\u0433\u043e \u043d\u0435\u0442, \u0430 \u0432\u043e\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0445 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u044d\u0442\u043e \u0443\u0436\u0435 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u0435\u0435.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">MyLua::eval('     print(phpconcat(\"a\", \"b\")) ');<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u043e\u0447\u0442\u0438 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u043d\u043e \u0441\u0442\u0440\u043e\u043a\u0438 \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u0432 Lua-\u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435. \u0414\u0430 \u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0432 PHP-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0417\u0430\u043c\u0435\u0442\u0438\u043c, \u0447\u0442\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u0437\u0430\u043c\u044b\u043a\u0430\u0435\u043c\u043e\u0435 \u043b\u044f\u043c\u0431\u0434\u0430\u043c\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0432 \u043d\u0430\u0448\u0435\u043c API \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0435\u0442:<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">class MyContext {     public $value = 0; }  $context = new MyContext(); MyLua::registerFunction0('next_id', function () use ($context) {     return $context->value++; });  MyLua::eval('     print(next_id()); -- 0     print(next_id()); -- 1 ');<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"ogranichivaem-dostup-k-standartnoy-biblioteke-lua\">\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 Lua<\/h2>\n<p>  <\/p>\n<p>\u0420\u0430\u043d\u0435\u0435 \u043c\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 <code>luaL_openlibs<\/code> \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 Lua. \u042d\u0442\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u0432\u0441\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043a \u0432\u044b\u0431\u043e\u0440\u043e\u0447\u043d\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0434\u043b\u044f Lua, \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431. \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>print<\/code>, \u0447\u0442\u043e\u0431\u044b \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043f\u0438\u0441\u0430\u043b\u0438 \u043d\u0435 \u0432 <code>stdout<\/code>, \u0430 \u0432 \u0432\u0430\u0448 \u0431\u0443\u0444\u0435\u0440. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <code>print<\/code>. \u041a\u0430\u043a \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e, <code>MyLua::registerFunction<\/code> \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u2014 \u044d\u0442\u0438\u043c \u0438 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">class LuaLogger {     public $messages = [];      public function doPrint($arg) {         $this->messages[] = $arg;         return null;     } }  $logger = new LuaLogger();  \/\/ \u041c\u0435\u0442\u043e\u0434\u044b \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0437\u0430\u043c\u044b\u043a\u0430\u0435\u043c\u044b\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u0436\u0435 \u043c\u043e\u0436\u043d\u043e. KLua::registerFunction1('print', [$logger, 'doPrint']);  \/\/ \u0412\u044b\u0437\u043e\u0432\u044b print \u0438\u0437 Lua \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 \/\/ \u043c\u0430\u0441\u0441\u0438\u0432 $logger->messages. KLua::eval('     print(1)     print(\"hello\") ');<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u0435\u0440\u043d\u0451\u043c\u0441\u044f \u043a \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0435. \u041f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0438\u043c \u043c\u043e\u0434\u0443\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u0441\u0442\u044c \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 Lua:<\/p>\n<p>  <\/p>\n<div class=\"scrollable-table\">\n<table>\n<thead>\n<tr>\n<th>\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u044f<\/th>\n<th>\u0424\u0443\u043d\u043a\u0446\u0438\u044f-\u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>base<\/code> (\u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u0442 <code>_G<\/code>)<\/td>\n<td><code>luaopen_base<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>package<\/code><\/td>\n<td><code>luaopen_package<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>coroutine<\/code><\/td>\n<td><code>luaopen_coroutine<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>table<\/code><\/td>\n<td><code>luaopen_table<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>io<\/code><\/td>\n<td><code>luaopen_io<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>os<\/code><\/td>\n<td><code>luaopen_os<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>string<\/code><\/td>\n<td><code>luaopen_string<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>math<\/code><\/td>\n<td><code>luaopen_math<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>utf8<\/code><\/td>\n<td><code>luaopen_utf8<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>debug<\/code><\/td>\n<td><code>luaopen_debug<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>  <\/p>\n<p>\u0423\u0436\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u043d\u0430\u043c <code>luaL_openlibs<\/code> \u0434\u0435\u043b\u0430\u0435\u0442 <a href=\"https:\/\/www.lua.org\/manual\/5.4\/manual.html#luaL_requiref\"><code>luaL_requiref<\/code><\/a> \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u043c\u043e\u0434\u0443\u043b\u0435\u0439. \u0415\u0441\u043b\u0438 \u0434\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043c\u0430\u0441\u0441\u0438\u0432 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439, \u0442\u043e \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u043e\u0447\u043d\u0443\u044e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u044c <code>base<\/code> \u0431\u0435\u0437 <code>luaL_openlibs<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">self::$lib->luaL_requiref(     self::$state, \"_G\", self::$lib->luaopen_base, 1);<\/code><\/pre>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u044d\u0442\u043e\u0442 \u043a\u043e\u0434, PHP \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0434\u043e\u0432\u043e\u043b\u0435\u043d:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># \u042f \u043e\u0442\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043b \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0432\u043e\u0441\u043f\u0440\u0438\u044f\u0442\u0438\u044f. FFI\\Exception:     Passing incompatible argument 3 of C function 'luaL_requiref',     expecting 'int32_t(*)()',     found     'int32_t(*)()'<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/xt\/lu\/t2\/xtlut2xuun4mvqyujd_esmnjwvy.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/xt\/lu\/t2\/xtlut2xuun4mvqyujd_esmnjwvy.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<p>\u0420\u0430\u0431\u043e\u0447\u0438\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u043b\u044f\u043c\u0431\u0434\u044b:<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">self::$lib->luaL_requiref(self::$state, \"_G\", function ($s) {     return self::$lib->luaopen_base($s); }, 1);<\/code><\/pre>\n<p>  <\/p>\n<p>\u042f \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u043c\u0435\u0442\u043e\u0434\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432\u0441\u0435\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u043f\u043e \u0438\u043c\u0435\u043d\u0438, \u043d\u043e \u043e\u043f\u0443\u0449\u0443 \u043e\u0434\u043d\u043e\u0442\u0438\u043f\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c:<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">\/\/ \u0413\u0434\u0435-\u0442\u043e \u043e\u043a\u043e\u043b\u043e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 lua_State. if ($config->preload_stdlib !== null) {     foreach ($config->preload_stdlib as $lib_name) {         self::openLib($lib_name);     } } else {     self::$lib->luaL_openlibs(self::$state); }  \/**  * @param string $lib_name  *\/ private static function openLib($lib_name) {     switch ($lib_name) {     case \"base\":         self::$lib->luaL_requiref(self::$state, \"_G\", function ($s) {             return self::$lib->luaopen_base($s);         }, 1);         break;     case \"package\":         self::$lib->luaL_requiref(self::$state, $lib_name, function ($s) {             return self::$lib->luaopen_package($s);         }, 1);         break;     case \"coroutine\":         \/\/ \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e...      \/\/ + \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0435\u0441\u044f \u043c\u043e\u0434\u0443\u043b\u0438 \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u0432\u044b\u0448\u0435.      default:         throw new \\Exception(\"can't load $lib_name\");     }     self::stackDiscard(1); \/\/ lib }<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"predostavlyaem-plaginam-krasivyy-sdk\">\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043b\u0430\u0433\u0438\u043d\u0430\u043c \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439 SDK<\/h2>\n<p>  <\/p>\n<p><code>MyLua::registerFunction<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u044d\u0442\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c \u0447\u0435\u0440\u0435\u0437 \u0442\u0430\u0431\u043b\u0438\u0446\u0443, \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044f \u043f\u0435\u0440\u0435\u0434 \u043f\u043b\u0430\u0433\u0438\u043d\u0430\u043c\u0438 \u043d\u0430\u0448 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 Lua-\u0441\u043a\u0440\u0438\u043f\u0442.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">\/\/ \u041c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0435\u0444\u0438\u043a\u0441 php_, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \/\/ \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u043a\u043e\u043b\u043b\u0438\u0437\u0438\u0439 \u0438\u043c\u0451\u043d. MyLua::registerFunction2('php_preg_match', function ($pat, $s) {     return preg_match($pat, $s) === 1; });  \/\/ \u041d\u0430\u0448 \u0441\u043a\u0440\u0438\u043f\u0442 \u0441 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u043c\u0438 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0434\u043e \/\/ \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u0434\u0430. MyLua::eval('     pcre = {}      function pcre.match(pat, s)         return php_preg_match(pat, s)     end ');  \/\/ \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \/\/ \u0447\u0435\u0440\u0435\u0437 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 pcre. MyLua::eval('     print(pcre.match(\"\/[0-9]+\/\", \"abc\")) -- true     print(pcre.match(\"\/[0-9]+\/\", \"435\")) -- false ');<\/code><\/pre>\n<p>  <\/p>\n<p>\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u2014 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430\u0448\u0435\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 PHP-\u0444\u0443\u043d\u043a\u0446\u0438\u0439. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0438\u043c\u044f \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0441\u0442\u043e\u0438\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e.<\/p>\n<p>  <\/p>\n<h2 id=\"tyunim-proizvoditelnost\">\u0422\u044e\u043d\u0438\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c<\/h2>\n<p>  <\/p>\n<p>\u0421\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430 \u043d\u0430 PHP \u0438\u043b\u0438 KPHP \u2014 \u044d\u0442\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a <a href=\"https:\/\/github.com\/VKCOM\/ktest\">ktest<\/a>. \u0415\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 composer:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ composer require --dev vkcom\/ktest-script<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u0440\u0430\u0437\u0443 \u0436\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0432\u0441\u0451 \u0445\u043e\u0440\u043e\u0448\u043e:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ .\/vendor\/bin\/ktest --help Usage:    ktest COMMAND  Possible commands are:    phpunit         run phpunit tests using KPHP   compare         test that KPHP and PHP scripts output is identical   benchstat       compute and compare statistics about benchmark results   bench           run benchmarks using KPHP   bench-ab        run two selected benchmarks using KPHP, compare results   bench-php       run benchmarks using PHP   bench-vs-php    run benchmarks using KPHP and PHP, compare results   env             print ktest-related env variables   version         print ktest version info  Run 'ktest COMMAND -h' to see more information about a command.<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b <code>benchmarks\/BenchmarkMyLua.php<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">&lt;?php  class BenchmarkMyLua {     public function __construct() {         if (KPHP_COMPILER_VERSION) {             FFI::load(__DIR__ . '\/lua.h');         }          MyLua::init();          MyLua::registerFunction2('phpconcat', function ($x, $y) {             return $x . $y;         });         MyLua::registerFunction2('phpmin', function ($x, $y) {             return min($x, $y);         });     }      public function benchmarkCall2PHPMin() {         return MyLua::call('phpmin', 1, 2);     }      public function benchmarkCall2PHPConcat() {         return MyLua::call('phpconcat', 'a', 'b');     }      public function benchmarkEvalPHPConcat() {         return MyLua::eval('return phpconcat(\"a\", \"b\")');     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u0438 \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0440\u0435\u0436\u0438\u043c\u0430\u0445. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u0430\u043c\u044b\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435.<\/p>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a \u0447\u0435\u0440\u0435\u0437 KPHP:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ .\/vendor\/bin\/ktest bench --benchmem .\/benchmarks class: BenchmarkMyLua BenchmarkMyLua::Call2PHPMin 126440  507.0 ns\/op 0 B\/op  0 allocs\/op BenchmarkMyLua::Call2PHPConcat  68980   924.0 ns\/op 32 B\/op 2 allocs\/op BenchmarkMyLua::EvalPHPConcat   13260   7580.0 ns\/op    1662 B\/op   56 allocs\/op ok BenchmarkMyLua 972.144303ms<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f KPHP \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0444\u043b\u0430\u0433 <code>--benchmem<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u043e\u0432 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043c, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0430\u043c\u044f\u0442\u0438 \u0431\u044b\u043b\u043e \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043e. \u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c Lua \u0447\u0435\u0440\u0435\u0437 <code>MyLua::call<\/code> \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0447\u0435\u043c \u0447\u0435\u0440\u0435\u0437 <code>eval<\/code>. \u041a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c, \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0432 \u0431\u0430\u0439\u0442-\u043a\u043e\u0434. \u0423 \u0432\u0430\u0448\u0438\u0445 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430, \u0432\u0440\u043e\u0434\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>run<\/code> \u0438\u043b\u0438 <code>main<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0438\u0445 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0438\u043c\u0435\u043d\u043d\u043e \u0447\u0435\u0440\u0435\u0437 <code>MyLua::call<\/code>. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0432\u0430\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 (<code>_ENV<\/code>) \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a \u0447\u0435\u0440\u0435\u0437 PHP (\u043f\u043e\u043a\u0430 \u043d\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0434\u043b\u044f <code>--benchmem<\/code>):<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ php --version PHP 8.1.8 (cli) (built: Jul 11 2022 08:29:57) (NTS) Copyright (c) The PHP Group Zend Engine v4.1.8, Copyright (c) Zend Technologies     with Zend OPcache v8.1.8, Copyright (c), by Zend Technologies  $ .\/vendor\/bin\/ktest bench-php --preload preload.php .\/benchmarks class: BenchmarkMyLua BenchmarkMyLua::Call2PHPMin 5260    9986.0 ns\/op BenchmarkMyLua::Call2PHPConcat  8120    10120.0 ns\/op BenchmarkMyLua::EvalPHPConcat   1460    74153.0 ns\/op ok BenchmarkMyLua 456.230781ms<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0434\u043b\u044f PHP8 \u0442\u0435\u0441\u0442\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u0441 \u0442\u0430\u043a\u0438\u043c\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 JIT:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">opcache.enable_cli=1 opcache.jit_buffer_size=96M opcache.jit=on<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0433\u043e\u043d\u044f\u0442\u044c PHP8 \u0431\u0435\u0437 JIT:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ .\/vendor\/bin\/ktest bench-php --no-jit --preload preload.php .\/benchmarks class: BenchmarkMyLua BenchmarkMyLua::Call2PHPMin 6840    9413.0 ns\/op BenchmarkMyLua::Call2PHPConcat  7880    9980.0 ns\/op BenchmarkMyLua::EvalPHPConcat   1460    79526.0 ns\/op ok BenchmarkMyLua 442.669261ms<\/code><\/pre>\n<p>  <\/p>\n<p>\u0410 \u0435\u0449\u0451 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0440\u0435\u0436\u0438\u043c \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f KPHP-vs-PHP:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\"># \u0420\u0430\u0437\u0431\u0438\u043b \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043d\u0430 \u0434\u0432\u0435 \u0441\u0442\u0440\u043e\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u0443\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u043f\u043e \u0448\u0438\u0440\u0438\u043d\u0435. $ .\/vendor\/bin\/ktest bench-vs-php --geomean\\     --preload preload.php .\/benchmarks name                   PHP time\/op  KPHP time\/op  delta MyLua::Call2PHPMin     9.35\u00b5s \u00b1 1%  0.49\u00b5s \u00b1 0%  -94.71%  (p=0.000 n=9+9) MyLua::Call2PHPConcat  10.3\u00b5s \u00b1 4%   0.9\u00b5s \u00b1 2%  -91.36%  (p=0.000 n=10+10) MyLua::EvalPHPConcat   79.3\u00b5s \u00b1 1%   7.5\u00b5s \u00b1 0%  -90.53%  (p=0.000 n=10+9) [Geo mean]             19.7\u00b5s        1.5\u00b5s       -92.43%<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, PHP FFI \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u0435\u043d, \u0438 JIT \u0437\u0434\u0435\u0441\u044c \u043f\u043e\u043c\u043e\u0447\u044c \u043f\u043e\u043a\u0430 \u043d\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u0435\u043d. \u041b\u044e\u0431\u043e\u043f\u044b\u0442\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u043a\u0430\u043a \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u0441\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 JIT \u043d\u0430\u0447\u043d\u0451\u0442 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u043a\u043e\u0434.<\/p>\n<p>  <\/p>\n<p>\u0412 KPHP \u0432\u044b\u0437\u043e\u0432\u044b FFI \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u044b\u0435. \u041c\u043e\u0436\u043d\u043e \u0434\u0430\u0436\u0435 \u043d\u0435 \u0437\u0430\u0434\u0443\u043c\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043e \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0445 \u0440\u0430\u0441\u0445\u043e\u0434\u0430\u0445, \u0435\u0441\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u0447\u044c \u0438\u0434\u0451\u0442 \u043d\u0435 \u043e \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0445 getter-\u0444\u0443\u043d\u043a\u0446\u0438\u044f\u0445. \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0437\u043c\u0435\u0440\u0438\u0442\u044c \u0437\u0430\u0442\u0440\u0430\u0442\u044b \u043d\u0430 \u0432\u044b\u0437\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0430.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">&lt;?php  class BenchmarkFFI {     \/** @var ffi_scope&lt;lua> *\/     private $lib;     \/** @var ffi_cdata&lt;lua, struct lua_State*> *\/     private $state;      public function __construct() {         if (KPHP_COMPILER_VERSION) {             FFI::load(__DIR__ . '\/..\/src\/lua.h');         }         $this->lib = FFI::scope('lua');         $this->state = $this->lib->luaL_newstate();     }      public function benchmarkGettop() {         return $this->lib->lua_gettop($this->state);     } }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"bash\">$ .\/vendor\/bin\/ktest bench .\/benchmarks\/BenchmarkFFI class: BenchmarkFFI BenchmarkFFI::Gettop    689660  17.0 ns\/op ok BenchmarkFFI 260.789974ms<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u043a\u043e\u043b\u043e 17 \u043d\u0430\u043d\u043e\u0441\u0435\u043a\u0443\u043d\u0434 \u043d\u0430 \u0432\u044b\u0437\u043e\u0432 <code>lua_gettop<\/code>. \u041d\u0435\u043f\u043b\u043e\u0445\u043e, \u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043b\u0443\u0447\u0448\u0435.<\/p>\n<p>  <\/p>\n<p>\u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 KPHP \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0441\u0435\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e FFI-\u0432\u044b\u0437\u043e\u0432\u0430. \u0422\u0430\u043a \u043e\u043d \u0437\u0430\u0449\u0438\u0449\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043d\u0435\u043f\u0440\u0438\u044f\u0442\u043d\u043e\u0441\u0442\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u044b\u0437\u043e\u0432\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430. \u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0445 \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0432\u0440\u043e\u0434\u0435 <code>lua_gettop<\/code> \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0432 <code>lua.h<\/code>-\u0444\u0430\u0439\u043b\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0443\u044e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442 \u044d\u0442\u0438 \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0441\u0435\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"diff\">+ \/\/ @kphp-ffi-signalsafe   int lua_gettop(lua_State *L);<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a \u0435\u0449\u0451 \u0440\u0430\u0437:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ .\/vendor\/bin\/ktest bench .\/benchmarks\/BenchmarkFFI class: BenchmarkFFI BenchmarkFFI::Gettop    862080  6.0 ns\/op ok BenchmarkFFI 253.012341ms<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u043d\u043e 6 \u043d\u0430\u043d\u043e\u0441\u0435\u043a\u0443\u043d\u0434! \u042d\u0442\u043e \u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442. \u041d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b \u043d\u0430 \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0441\u0435\u043a\u0446\u0438\u044e \u0431\u043b\u0438\u0437\u043a\u0438 \u043a \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0435 \u2014 \u043e\u043a\u043e\u043b\u043e 10 \u043d\u0430\u043d\u043e\u0441\u0435\u043a\u0443\u043d\u0434. \u0412 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u0438\u043b\u0438 \u043c\u0430\u043b\u043e. \u0427\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u2014 \u043a\u0430\u043f\u043b\u044f \u0432 \u043c\u043e\u0440\u0435. \u0414\u043b\u044f <code>lua_gettop<\/code> \u0441\u0447\u0438\u0442\u0430\u044e \u044d\u0442\u0443 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u043e\u043f\u0440\u0430\u0432\u0434\u0430\u043d\u043d\u043e\u0439.<\/p>\n<p>  <\/p>\n<h2 id=\"proizvoditelnost-rasshireniy-po-sravneniyu-s-ffi-v-php\">\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 FFI \u0432 PHP<\/h2>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0442\u0430\u043c \u0443 PHP:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ .\/vendor\/bin\/ktest bench-vs-php --preload preload.php\\     .\/benchmarks\/BenchmarkFFI.php  name         PHP time\/op  KPHP time\/op  delta FFI::Gettop   301ns \u00b1 1%     6ns \u00b1 0%  -98.00%  (p=0.000 n=8+10)<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043a\u0443\u0449\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 FFI \u0432 PHP \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0432\u044b\u0441\u043e\u043a\u0438\u0435 \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b \u043d\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 PHP \u0438 \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u043a\u043e\u0434\u043e\u043c. \u041e\u0434\u043d\u0430\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u0438\u043c\u0435\u0435\u043c \u0442\u0443 \u0436\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438.<\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c\u043e\u0441\u0442\u044c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043a\u0430\u043a\u0443\u044e-\u043d\u0438\u0431\u0443\u0434\u044c \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u0443\u0436\u0435 \u043d\u0435 \u0442\u0430\u043a \u043f\u0440\u0438\u044f\u0442\u043d\u043e: \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u043b\u043e\u0432\u0438\u043d\u044b \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0439\u0442\u0438\u0441\u044c \u043d\u0430 \u0432\u044b\u0437\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0430 \u043d\u0435 \u043d\u0430 \u0435\u0451 \u0440\u0430\u0431\u043e\u0442\u0443. \u041e\u0434\u043d\u0430\u043a\u043e \u0440\u0430\u0441\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0432\u043e\u0434\u0443 \u0440\u0430\u043d\u043e, \u0432\u0435\u0434\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043d\u0430 \u0440\u0430\u0434\u0430\u0440\u0435 \u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043b\u044e\u0434\u0435\u0439 \u0438 \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0439 \u0434\u0430\u0436\u0435 300 \u043d\u0430\u043d\u043e\u0441\u0435\u043a\u0443\u043d\u0434 \u043d\u0430 \u0432\u044b\u0437\u043e\u0432 \u2014 \u043d\u0435 \u043a\u0430\u0442\u0430\u0441\u0442\u0440\u043e\u0444\u0430. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443, \u0442\u043e \u043c\u044b \u0434\u0430\u0436\u0435 \u043d\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u043c \u044d\u0442\u0438 \u043b\u0438\u0448\u043d\u0438\u0435 0,0000003 \u0441\u0435\u043a\u0443\u043d\u0434\u044b.<\/p>\n<p>  <\/p>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043d\u0430 Lua. \u0412\u044b\u0441\u043e\u043a\u0430 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c, \u0447\u0442\u043e \u0434\u0430\u0436\u0435 \u043d\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u043c \u0432\u043b\u0438\u044f\u043d\u0438\u044f FFI \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c. \u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0443\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0441 PHP-\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u0441\u043c\u043e\u0436\u0435\u043c \u043b\u0438 \u043c\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0440\u0430\u0437\u043d\u0438\u0446\u0443.<\/p>\n<p>  <\/p>\n<p>\u041c\u044b \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c <a href=\"https:\/\/benchmarksgame-team.pages.debian.net\/benchmarksgame\/program\/spectralnorm-lua-1.html\">spectral norm<\/a> \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c N=25 (\u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u043c\u0430\u043b\u043e). \u0414\u043b\u044f <code>use_ffi_allocator=false<\/code> \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">name                ext time\/op  ffi time\/op  delta LuaExtension::Eval  3.45ms \u00b1 1%  3.47ms \u00b1 1%  +0.53%  (p=0.002 n=10+10)<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u0447\u0438\u0442\u0430\u044e \u044d\u0442\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u043e\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e. \u041e\u0431\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442 Lua-\u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 <a href=\"https:\/\/github.com\/laruence\/php-lua\/blob\/a6c5162a7cbdf4b48b104f303acc022a3f93caf2\/lua.c#L196\">\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440<\/a> (\u0438\u0437 glibc).<\/p>\n<p>  <\/p>\n<p>\u041c\u043e\u0436\u0435\u043c \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u044c \u0438 FFI-\u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440 \u043f\u0430\u043c\u044f\u0442\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">name                ext time\/op  ffi time\/op  delta LuaExtension::Eval  3.45ms \u00b1 1%  3.93ms \u00b1 0%  +13.81%  (p=0.000 n=10+10)<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"podderzhka-light-userdata\">\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 light userdata<\/h2>\n<p>  <\/p>\n<p>\u0420\u0430\u043d\u0435\u0435 \u043c\u044b \u043e\u0431\u043e\u0448\u043b\u0438 \u0442\u0438\u043f <a href=\"https:\/\/www.lua.org\/pil\/28.5.html\">light userdata<\/a> \u0441\u0442\u043e\u0440\u043e\u043d\u043e\u0439. \u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u043e, \u043d\u043e \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u0435\u0437\u0435\u043d. \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0434\u0430\u043d\u043d\u044b\u0445. \u0415\u0441\u043b\u0438 \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c \u0435\u0433\u043e \u0438\u0437 PHP \u0432 Lua \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e, \u0442\u043e \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0442\u0430\u043a\u043e\u043c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0438. Light userdata \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043e\u0431\u043e\u0438\u0445 \u044f\u0437\u044b\u043a\u0430\u0445 \u0431\u0435\u0437 \u043d\u0435\u044f\u0432\u043d\u043e\u0439 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438. \u0422\u0430\u043a \u043c\u044b \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0438\u0437\u0431\u0435\u0433\u0430\u0435\u043c \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0442\u043e \u043c\u0430\u0441\u0441\u0438\u0432 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 C-\u0434\u0430\u043d\u043d\u044b\u0445, \u0430 \u043d\u0435 \u043a\u0430\u043a PHP-\u043c\u0430\u0441\u0441\u0438\u0432. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 C-\u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u0438\u0437 \u043d\u0430\u0448\u0435\u0433\u043e PHP-\u043c\u0430\u0441\u0441\u0438\u0432\u0430.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u043f\u0438\u0448\u0435\u043c \u043d\u0430\u0448 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f userdata:<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">class UserData {     \/** @var ffi_scope&lt;lua_userdata> *\/     public static $lib;      public static function init() {         self::$lib = FFI::cdef('             #define FFI_SCOPE \"lua_userdata\"             struct ContextData {                 int important_data[100];             };         ');     }      \/** @return ffi_cdata&lt;lua_userdata, struct ContextData> *\/     public static function newContextData($important_data) {         $ctx = self::$lib->new('struct ContextData');         for ($i = 0; $i &lt; count($ctx->important_data); $i++) {             ffi_array_set($ctx->important_data, $i, $i * 2);         }         return $ctx;     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c <code>lua2php<\/code>, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b\u0441\u044f \u043d\u043e\u0432\u044b\u0439 \u0442\u0438\u043f:<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">case self::TLIGHTUSERDATA:     $void_ptr = self::$lib->lua_touserdata(self::$state, $index);     return ffi_cast_ptr2addr($void_ptr);<\/code><\/pre>\n<p>  <\/p>\n<p><code>lua2php<\/code> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 <code>mixed<\/code>. \u0412 KPHP \u043d\u0435\u043b\u044c\u0437\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0442\u0430\u043a \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0442\u0438\u043f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 \u0438 <code>mixed<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 <code>mixed|CData<\/code> \u043d\u0430\u043c \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442. \u0422\u0430\u043a \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c <code>void*<\/code> \u043c\u044b \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0432 \u0447\u0438\u0441\u043b\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u0430 <code>int<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0430\u0434\u0440\u0435\u0441. \u0415\u0433\u043e \u043f\u043e\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f <a href=\"https:\/\/www.php.net\/manual\/ru\/class.ffi-cdata.php\"><code>CData<\/code><\/a>.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">KLua::registerFunction2('ctx_get', function ($ctx_addr, $index) {     \/\/ userdata-\u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a PHP int.     \/\/ \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u0430\u0434\u0440\u0435\u0441\u0443,     \/\/ \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c ffi_cast_addr2ptr.     $ptr = ffi_cast_addr2ptr((int)$vec_addr);     \/\/ \u0422\u0430\u043a \u043a\u0430\u043a $ptr - \u044d\u0442\u043e void*, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c     \/\/ \u0435\u0449\u0451 \u043e\u0434\u0438\u043d cast \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c.     $ctx = UserData::$lib->cast('struct ContextData*', $ptr);     return ffi_array_get($ctx->important_data, $index); });<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0432 Lua \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 userdata \u2014 \u0447\u0435\u0440\u0435\u0437 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">\/**  * @param string $var_name  * @param ffi_cdata&lt;C, void*>  *\/ public static function setVarUserData($var_name, $ptr) {     self::$lib->lua_pushlightuserdata(self::$state, $ptr);     self::$lib->lua_setglobal(self::$state, $var_name); }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"php\">UserData::init(); $ctx = UserData::newContextData(); MyLua::setVarUserData('global_ctx', FFI::addr($ctx));<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f Lua \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f userdata \u043d\u0435\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u044b, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0441\u0451, \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441 \u043d\u0438\u043c\u0438, \u044d\u0442\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u0445 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0435 \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">MyLua::eval('     print(ctx_get(global_ctx, 0)) -- 0.0     print(ctx_get(global_ctx, 1)) -- 2.0     print(ctx_get(global_ctx, 2)) -- 4.0 ');<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 Lua \u0438 PHP \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u0435, \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0439 \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>\u041a\u0430\u043a \u0432\u044b \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0442\u0438\u043f\u0430 <code>ffi_array_set<\/code> \u0438 <code>ffi_cast_addr2ptr<\/code>. \u041e\u043d\u0438 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u044b \u0432 KPHP \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u0446\u0438\u0438 FFI-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439; \u0432 PHP \u043e\u043d\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/github.com\/VKCOM\/kphp-polyfills\">kphp-polyfills<\/a>.<\/p>\n<p>  <\/p>\n<h2 id=\"klua\">KLua<\/h2>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/91\/ku\/eo\/91kueo4r2em2cwlymh5ff8bqv74.png\" data-src=\"https:\/\/habrastorage.org\/webt\/91\/ku\/eo\/91kueo4r2em2cwlymh5ff8bqv74.png\"\/><\/p>\n<p>  <\/p>\n<p>\u041f\u0430\u043a\u0435\u0442 <a href=\"https:\/\/github.com\/quasilyte\/KLua\">quasilyte\/klua<\/a> \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0432\u0441\u0451 \u0442\u043e, \u043e \u0447\u0451\u043c \u043c\u044b \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u0438 \u0432\u044b\u0448\u0435, \u0438 \u0434\u0430\u0436\u0435 \u0431\u043e\u043b\u044c\u0448\u0435. \u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u0434\u043b\u044f PHP, \u0442\u0430\u043a \u0438 \u0434\u043b\u044f KPHP. \u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0435\u0451 API \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0432\u0430\u043c \u0447\u0435\u043c-\u0442\u043e \u043d\u0435\u043e\u0431\u044b\u0447\u043d\u044b\u043c. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u043f\u0430\u043a\u0435\u0442 \u043c\u043e\u0436\u043d\u043e \u0447\u0435\u0440\u0435\u0437 composer:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ composer require quasilyte\/klua<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"php\">&lt;?php  require_once __DIR__ . '\/vendor\/autoload.php';  use KLua\\KLua; use KLua\\KLuaConfig;  if (KPHP_COMPILER_VERSION) { KLua::loadFFI(); }  KLua::init(new KLuaConfig());  KLua::eval('     function example(x)         return x + 1     end ');  var_dump(KLua::call('example', 10)); \/\/ => 11<\/code><\/pre>\n<p>  <\/p>\n<p>KLua \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0430\u0441\u044c \u0441 Lua \u0432\u0435\u0440\u0441\u0438\u0439 5.2, 5.3 \u0438 5.4.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 KLua:<\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/quasilyte\/KLua\/blob\/master\/examples\/1_simple.php\">simple.php<\/a> \u2014 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 hello world.<\/li>\n<li><a href=\"https:\/\/github.com\/quasilyte\/KLua\/blob\/master\/examples\/2_phpfunc.php\">phpfunc.php<\/a> \u2014 \u043f\u0440\u0438\u043c\u0435\u0440 \u0441 <code>registerFunction<\/code>.<\/li>\n<li><a href=\"https:\/\/github.com\/quasilyte\/KLua\/blob\/master\/examples\/3_override_print.php\">override_print.php<\/a> \u2014 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 <code>print<\/code> \u0432 Lua.<\/li>\n<li><a href=\"https:\/\/github.com\/quasilyte\/KLua\/blob\/master\/examples\/4_limited_stdlib.php\">limited_stdlib.php<\/a> \u2014 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0439 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438.<\/li>\n<li><a href=\"https:\/\/github.com\/quasilyte\/KLua\/blob\/master\/examples\/5_plugin_sandbox.php\">plugin_sandbox.php<\/a> \u2014 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u0441 \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u0435\u0439.<\/li>\n<li><a href=\"https:\/\/github.com\/quasilyte\/KLua\/blob\/master\/examples\/6_phpfunc_table.php\">phpfunc_table.php<\/a> \u2014 \u043a\u0430\u043a \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c PHP-\u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0443.<\/li>\n<li><a href=\"https:\/\/github.com\/quasilyte\/KLua\/blob\/master\/examples\/7_userdata.php\">userdata.php<\/a> \u2014 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f light userdata.<\/li>\n<li><a href=\"https:\/\/github.com\/quasilyte\/KLua\/blob\/master\/examples\/8_memory_limit.php\">memory_limit.php<\/a> \u2014 \u043a\u0430\u043a \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0443\u044e Lua-\u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c.<\/li>\n<li><a href=\"https:\/\/github.com\/quasilyte\/KLua\/blob\/master\/examples\/9_time_limit.php\">time_limit.php<\/a> \u2014 \u043a\u0430\u043a \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c\u044b\u0445 Lua-\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432.<\/li>\n<\/ul>\n<p>  <\/p>\n<h2 id=\"poleznye-istochniki\">\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438<\/h2>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/quasilyte\/KLua\">KLua<\/a> \u2014 FFI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f liblua5.<\/li>\n<li><a href=\"https:\/\/t.me\/kphp_chat\">t.me\/kphp_chat<\/a> \u2014 \u0447\u0430\u0442\u0438\u043a open-source \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0430 KPHP.<\/li>\n<li><a href=\"https:\/\/github.com\/quasilyte\/awesome-kphp\/\">awesome-kphp<\/a><\/li>\n<li>\u0421\u0442\u0430\u0442\u044c\u044f <a href=\"https:\/\/habr.com\/ru\/post\/653677\/\">\u00ab\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c SQLite \u0432 KPHP \u0438 PHP \u0447\u0435\u0440\u0435\u0437 FFI\u00bb<\/a>.<\/li>\n<li>\u0421\u0442\u0430\u0442\u044c\u044f <a href=\"https:\/\/habr.com\/ru\/company\/vk\/blog\/581238\/\">\u00ab\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0438\u0433\u0440\u0443 \u043d\u0430 KPHP \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e FFI \u0438 SDL\u00bb<\/a>.<\/li>\n<li>\u0421\u0442\u0430\u0442\u044c\u044f <a href=\"https:\/\/habr.com\/ru\/company\/vk\/blog\/572424\/\">\u00ab\u0417\u0430\u043c\u0435\u0442\u043a\u0438 KPHP: \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0438\u00bb<\/a>.<\/li>\n<li>\u0414\u043e\u043a\u043b\u0430\u0434 \u043f\u0440\u043e <a href=\"https:\/\/speakerdeck.com\/quasilyte\/kphp-ffi\">KPHP FFI<\/a>.<\/li>\n<li><a href=\"https:\/\/vkcom.github.io\/kphp\/kphp-language\/php-extensions\/ffi.html\">\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f KPHP FFI<\/a>.<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/vk\/blog\/681400\/\"> https:\/\/habr.com\/ru\/company\/vk\/blog\/681400\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><a href=\"https:\/\/www.php.net\/manual\/ru\/class.ffi.php\">Foreign Function Interface<\/a> \u2014 \u044d\u0442\u043e \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u043d\u0430\u044f \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 \u0434\u043b\u044f \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u0445 PHP-\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439.<\/p>\n<p>  <\/p>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c FFI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <a href=\"https:\/\/www.lua.org\/manual\/5.3\/\">liblua5<\/a> \u0438\u0437 PHP, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043d\u0430 Lua \u0438\u0437 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/xv\/em\/nl\/xvemnlq_kqrasv7-eqlz0uy4hdc.png\" data-src=\"https:\/\/habrastorage.org\/webt\/xv\/em\/nl\/xvemnlq_kqrasv7-eqlz0uy4hdc.png\"\/><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-337452","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/337452","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=337452"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/337452\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=337452"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=337452"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=337452"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}