{"id":398204,"date":"2024-06-29T13:56:08","date_gmt":"2024-06-29T13:56:08","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=398204"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=398204","title":{"rendered":"<span>Lua 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\">\u041f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u043e\u0433\u043e <abbr title=\"Foreign Function Interface\">FFI<\/abbr> \u0434\u043b\u044f Lua \u043f\u043e\u0434 x64 windows, \u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u0435\u0449\u0451 \u0438 linux (\u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e, SysV ABI). <\/p>\n<p>  \u041d\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u0442\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c:<\/p>\n<pre><code class=\"lua\">local ffi = require (\"ffi\") local msg = ffi(\"user32.dll\", \"MessageBoxA\") msg(0, \"Message\", \"Title\", 0)<\/code><\/pre>\n<p>  \u0438\u043b\u0438 \u0432\u0437\u044f\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 glfw3.dll, \u0438 \u043f\u0443\u0442\u0451\u043c<\/p>\n<pre><code class=\"lua\">local glfw = ffi(\"glfw3\")<\/code><\/pre>\n<p>  \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0441\u0435 \u044d\u043ac\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 glfw3.dll \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c\u0438 \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u0438\u0437 Lua.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/pa\/m4\/0x\/pam40xaogfwbdladb_-d6fv5nuy.png\" align=\"right\" data-src=\"https:\/\/habrastorage.org\/webt\/pa\/m4\/0x\/pam40xaogfwbdladb_-d6fv5nuy.png\"\/>\u0420\u0430\u0437\u043c\u0435\u0440 \u0441\u0430\u043c\u043e\u0439 ffi.dll \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f \u0430\u0436 9 \u041a\u0431\u0430\u0439\u0442, \u0432\u043e\u0442 \u043e\u043d\u0430 \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u043d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c 32\u044596 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439. \u041c\u043e\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u044d\u0442\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u0441\u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 bmp (\u0445\u0430\u0431\u0440 \u043d\u0435 \u0443\u043c\u0435\u0435\u0442 \u0432 bmp, \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c \u0432 png), \u043f\u043e\u0442\u043e\u043c \u0440\u0443\u043a\u0430\u043c\u0438 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0435 54 \u0431\u0430\u0439\u0442\u0430 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 (\u0434\u043e &#8216;MZ&#8217;) \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f.<\/p>\n<p>  \u041d\u043e \u043e\u0447\u0435\u043d\u044c \u043e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u0432 \u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u0443\u044e \u0434\u0435\u0442\u0441\u043a\u0443\u044e \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0443 Lua \u0437\u0430\u043b\u0435\u0437\u043b\u0438 \u0433\u0440\u044f\u0437\u043d\u044b\u043c\u0438 \u0441\u0430\u043f\u043e\u0433\u0430\u043c\u0438, \u043f\u0440\u0438\u0442\u0430\u0449\u0438\u043b\u0438 \u0442\u0443\u0434\u0430 \u0432\u0441\u044f\u043a\u0438\u0435 \u043d\u0435\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0435 \u0448\u0442\u0443\u043a\u0438 \u0438\u0437 \u0421, \u0432\u0440\u043e\u0434\u0435 \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u044c\u044e \u0438 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u0441 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f\u043c\u0438 \u0432\u0438\u0434\u0430 *(double*) (void * ptr), \u0438 \u0432\u043e\u043e\u0431\u0449\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0430\u043a\u0438\u0445 \u0432\u0435\u0449\u0435\u0439 \u0443\u0447\u0438\u0442 \u0432\u0441\u044f\u043a\u043e\u043c\u0443 \u043d\u0435\u0445\u043e\u0440\u043e\u0448\u0435\u043c\u0443. <\/p>\n<p>  \u0422\u0443\u0442 \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u0432\u044b\u0445\u043e\u0434\u0438\u043b \u0440\u044f\u0434 \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u0440\u043e \u00ab\u0432\u0440\u0435\u0434\u043d\u044b\u0435 \u0441\u043e\u0432\u0435\u0442\u044b\u00bb \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u00ab60 \u0430\u043d\u0442\u0438\u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u0432 \u0434\u043b\u044f \u0421++ \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0430\u00bb. \u041f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0432\u043e\u043f\u043b\u043e\u0449\u0435\u043d\u0438\u0435 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u0438\u0437 \u043d\u0438\u0445, \u043d\u0435 \u0432\u0441\u0435\u0445 \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043d\u0435 \u0432\u0441\u0435 \u0438\u0437 \u043d\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c\u044b \u043a \u0421, \u0431\u0435\u0437 \u043f\u043b\u044e\u0441\u043e\u0432 \ud83d\ude42<br \/>  <a name=\"habracut\"><\/a><br \/>  \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u2014 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0438 \u0431\u043e\u0433\u0430\u0442\u043e\u0433\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u043c\u0438\u0440\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438.<\/p>\n<p>  \u0427\u0442\u043e\u0431\u044b \u043d\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0432\u0441\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u043e\u0434\u0440\u044f\u0434, \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/p>\n<pre><code class=\"lua\">local gl = ffi(\"opengl32\", {\"glClearColor\", \"glClear\", \"glViewport\"})<\/code><\/pre>\n<p>  \u0417\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0435 \u0438\u0437 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0435\u0441\u043b\u0438 \u0438\u0445 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e, \u0438 \u0442\u0430\u043a \u0441\u0438\u0434\u044f\u0442 \u0432 \u0441\u0432\u043e\u0435\u0439 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 (\u0441\u0447\u0438\u0442\u0430\u0439 namespace), \u0442\u0430\u043a \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0443\u0431\u0440\u0430\u0442\u044c \u0438\u0437 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043f\u0440\u0435\u0444\u0438\u043a\u0441, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a glfw.Init()<\/p>\n<pre><code class=\"lua\">local glfw = {} for k,v in pairs(ffi(\"glfw3\",\"*\")) do glfw[k:match(\"^glfw(.+)\") or k] = v end<\/code><\/pre>\n<p>  \u043b\u0438\u0431\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438\u0445 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u043c\u0438<\/p>\n<pre><code class=\"lua\">for k,v in pairs(ffi(\"glfw3\",\"*\")) do _G[k] = v end<\/code><\/pre>\n<p>  \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a glfwInit()<\/p>\n<h2>\u0422\u0438\u043f \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432<\/h2>\n<p>  \u0422\u0438\u043f \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043f\u043e \u043e\u0434\u043d\u043e\u0439 \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u044f\u0432\u043d\u043e<\/p>\n<pre><code class=\"lua\">local cosf = ffi(\"msvcrt.dll\", \"cosf\", \"ff\") print( cosf(math.pi \/ 3), math.cos(math.pi \/ 3) )<\/code><\/pre>\n<p>  \u0442\u043e\u0433\u0434\u0430 \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u0441\u0434\u0435\u043b\u0430\u043d\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u0438 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043e \u0447\u0438\u0441\u043b\u043e, \u0441\u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0432\u043e float, \u0430 \u0432 Lua \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0451\u043d \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0434\u043b\u044f \u043d\u0435\u0451 lua_Number \u0442.\u0435. double.<\/p>\n<p>  C\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u0430 C-\u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u043e\u043a\u0438, \u043f\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0443 \u043d\u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442: &#8216;v&#8217; = void, &#8216;i&#8217; = int, &#8216;f&#8217; = float, &#8216;d&#8217; = double, &#8216;b&#8217; = boolean, &#8216;p&#8217; = pointer, &#8216;s&#8217; = string. \u041f\u0435\u0440\u0432\u044b\u043c \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u043c \u2014 \u0432\u0441\u0435\u0433\u0434\u0430 \u0442\u0438\u043f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0437\u0430\u0442\u0435\u043c \u0430\u0433\u0440\u0443\u043c\u0435\u043d\u0442\u044b.<\/p>\n<p>  \u041c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u0442\u044c \u0438 \u0447\u0435\u043b\u043e\u0432\u0435\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0430\u0440\u0441\u0435\u0440 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 \u0421, \u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0430\u0440\u0441\u0435\u0440, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0435 \u043f\u0430\u0434\u0430\u043b \u043e\u0442 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 \u0432\u0438\u0434\u0430 \u00ab\u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 &#8230;\u00bb \u043a\u0430\u043a-\u0442\u043e \u0441\u0445\u043e\u0434\u0443 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c, \u043f\u043e\u043b\u043d\u043e\u0433\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u0438\u044f \u0442\u0438\u043f\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 Lua \u0438 \u0421 \u0442\u043e\u0436\u0435 \u043d\u0435\u0442 \u0438 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043a\u0430\u043a\u0438\u0445-\u043d\u0438\u0431\u0443\u0434\u044c \u043a\u043e\u0441\u0442\u044b\u043b\u0435\u0439, \u0434\u0430 \u0438 \u043f\u0440\u0438\u043a\u0440\u0443\u0447\u0438\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043f\u0430\u0440\u0441\u0435\u0440 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u044b\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u043a\u0430 \u0442\u0430\u043a, \u043f\u043e\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0432\u0435\u0440\u0445.<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u044b, \u0442\u0438\u043f\u044b \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0442\u0438\u043f\u043e\u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0445 \u043f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0435\u0439\u0441\u044f Lua \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043e\u0431\u0451\u0440\u0442\u043ae \u043f\u0440\u0438 \u0435\u0451 \u0432\u044b\u0437\u043e\u0432\u0435.<\/p>\n<p>  \u041e\u0434\u043d\u0430\u043a\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u0446\u0435\u043b\u043e\u043c \u0441 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432 Lua \u0442\u0430\u043a \u0441\u0435\u0431\u0435, \u0430 \u0434\u043b\u044f \u043f\u043b\u0430\u0432\u0430\u044e\u0449\u0435\u0439 \u0437\u0430\u043f\u044f\u0442\u043e\u0439 \u0435\u0441\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e double, \u0442\u043e \u0447\u0442\u043e\u0431\u044b \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u0447\u043d\u0443\u044e \u0421-\u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e float, \u0435\u0441\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 ffi.float(x), \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0447\u0438\u0441\u043b\u043e \u0432\u043e float \u0438 \u043f\u0430\u043a\u0443\u0435\u0442 \u0435\u0433\u043e \u0432 \u043c\u043b\u0430\u0434\u0448\u0438\u0435 32 \u0440\u0430\u0437\u0440\u044f\u0434\u0430 double. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0435\u0441\u043b\u0438 \u0421 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 float, \u0435\u0433\u043e \u0442\u043e\u0436\u0435 \u043d\u0430\u0434\u043e \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u0442\u043e\u0442 \u0436\u0435 ffi.float(), \u0447\u0442\u043e\u0431\u044b \u0441\u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 lua_Number.<\/p>\n<pre><code class=\"lua\">local cosf = ffi(\"msvcrt.dll\", \"cosf\") print( ffi.float( cosf( ffi.float(math.pi \/ 3) ) ) )<\/code><\/pre>\n<p>  \u0424\u0443\u043d\u043a\u0446\u0438\u044f-\u043e\u0431\u0451\u0440\u0442\u043a\u0430 \u0441 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0442\u0438\u043f\u043e\u0432 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0434\u0432\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, (\u0438 \u0446\u0435\u043b\u044b\u0439 \u0438 \u0441 \u043f\u043b\u0430\u0432\u0430\u044e\u0449\u0435\u0439 \u0437\u0430\u043f\u044f\u0442\u043e\u0439 \u0438\u0437 \u043e\u0431\u043e\u0438\u0445 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u043e\u0432 rax \u0438 xmm0, \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043d\u0438\u0436\u0435) \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u0443 ffi.float \u0438 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0434\u043e \u00ab\u0437\u0430\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c\u00bb \u043e\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0430\u0434\u043e \u00ab\u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c\u00bb \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 double. \u0422\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 ffi.double, ffi.string, ffi.boolean, ffi.integer, ffi.pointer, \u0434\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0442\u0438\u043f\u043e\u0432 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 Lua.<\/p>\n<p>  \u0420\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c (<i>\u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ffi.userdata() \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0434\u0435\u043b\u044f\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 Lua \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u0432 \u0421<\/i>), \u043b\u0438\u0431\u043e \u043a\u0430\u043a \u0441\u0442\u0440\u043e\u043a\u0443 (<i>\u0432 Lua \u0435\u0441\u0442\u044c string.pack \u0434\u043b\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/i>), \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u044f, \u043a\u043e\u0433\u0434\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u0432\u043b\u0430\u0437\u0438\u0442 \u0432 8 \u0431\u0430\u0439\u0442, \u0442\u043e\u0433\u0434\u0430 \u0435\u0451 \u043d\u0430\u0434\u043e \u0443\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c \u0432 integer (\u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 calling convention).<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0441\u043e \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438, \u0442\u043e \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0430 \u0432 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u0434\u043b\u044f \u0421 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0434\u0435\u043b\u0435\u043d \u043c\u0430\u0441\u0441\u0438\u0432 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439 const char * \u043f\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0438 \u043f\u0440\u043e\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f\u043c\u0438 \u043d\u0430 \u0441\u0442\u0440\u043e\u043a\u0438, \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432 \u0441\u0442\u0440\u043e\u043a \u0442\u0438\u043f\u0430 const char **.<\/p>\n<p>  \u0422\u0430\u043a\u043e\u0439 \u00ab\u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u043d\u044b\u0439\u00bb \u043c\u0430\u0441\u0441\u0438\u0432 \u0436\u0438\u0432\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043a\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043d\u0430\u0440\u0443\u0436\u0443 \u043d\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0438 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0442\u043e\u043c \u0443\u043d\u0438\u0447\u0442\u043e\u0436\u0435\u043d \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u043e\u043c \u043c\u0443\u0441\u043e\u0440\u0430, \u0430 \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0421 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044e \u043d\u0438\u0447\u0435\u0433\u043e \u0445\u043e\u0440\u043e\u0448\u0435\u0433\u043e \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f, \u043d\u043e \u0438 \u0441\u043e\u0432\u0441\u0435\u043c \u043f\u043b\u043e\u0445\u043e\u0433\u043e, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0432\u044b\u0445\u043e\u0434\u0438\u0442\u044c \u0437\u0430 \u0440\u0430\u0437\u043c\u0435\u0440\u044b \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0442\u043e\u0436\u0435. \u0414\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043d\u0435\u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u043d\u043e\u0433\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0421 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0447\u0442\u043e-\u0442\u043e \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430\u0434\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0435\u0433\u043e \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b Lua \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ffi.userdata().<\/p>\n<p>  \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432<\/p>\n<pre><code class=\"cpp\">void glShaderSource(GLuint shader, GLsizei count, const GLchar **string, const GLint *length);<\/code><\/pre>\n<p>  \u0432 Lua \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043a\u0430\u043a <\/p>\n<pre><code class=\"lua\">gl.ShaderSource(shader, 2, {shader_src1, shader_src2}, 0)<\/code><\/pre>\n<p>  \u0422\u0430\u0431\u043b\u0438\u0446\u044b \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u043c\u0438, \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0431\u043e\u043b\u0435\u0435 \u043c\u043d\u043e\u0433\u043e\u043c\u0435\u0440\u043d\u044b\u0445 char ****.<\/p>\n<h2>Callback<\/h2>\n<p>  \u0415\u0441\u043b\u0438 \u0436\u0435 \u0432 ffi \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c Lua \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0430 \u043d\u0435 \u0441\u0442\u0440\u043e\u043a\u0443 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438\u043b\u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c (<i>\u043d\u0430 C \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u0435\u0440\u043d\u0443\u043b\u0430 \u043a\u0430\u043a\u0430\u044f-\u043d\u0438\u0431\u0443\u0434\u044c \u0434\u0440\u0443\u0433\u0430\u044f \u0421 \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u0432\u0440\u043e\u0434\u0435 wglGetProcAddress<\/i>), \u0442\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u0430\u044f Lua \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0430 \u0432 \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443, \u0432 callback (\u0421 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e).<\/p>\n<p>  \u0414\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 callback&#8217;\u043e\u0432 \u0438\u0437 Lua \u0432 \u0421 \u0442\u0438\u043f\u044b \u0430\u0440\u0433\u0443\u043c\u0435\u0442\u043d\u043e\u0432 \u043d\u0430\u0434\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u044f\u0432\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u0432\u044b\u0437\u044b\u0437\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0431\u0443\u0434\u0435\u0442 \u043a\u0442\u043e-\u0442\u043e \u0441\u043d\u0430\u0440\u0443\u0436\u0438 \u0438 \u043a\u0430\u043a-\u0442\u043e \u0438\u0437 \u0441\u0430\u043c\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0443\u0437\u043d\u0430\u0442\u044c \u0442\u0438\u043f\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u043c.<\/p>\n<pre><code class=\"lua\">local GLFW = {KEY_ESCAPE = 256, PRESS = 1, RELEASE = 0, TRUE = 1, FALSE = 0}  local function key_callback(window, key, scancode, action, mods) --  print(key,scancode,action)   if (key == GLFW.KEY_ESCAPE and action == GLFW.PRESS) then     glfw.SetWindowShouldClose(window, GLFW.TRUE)   end end  key_callback = ffi(key_callback, \"vpiiii\")  glfw.SetKeyCallback(window, key_callback);<\/code><\/pre>\n<p>  <\/p>\n<h2>\u0418\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b<\/h2>\n<p>  \u0418\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u2014 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u0435\u0447\u0430\u043b\u044c \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u0421 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0438\u0437 \u0434\u0440\u0443\u0433\u0438\u0445 \u044f\u0437\u044b\u043a\u043e\u0432, \u043d\u043e \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0439 \u043f\u0430\u0440\u0441\u0435\u0440 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0434\u0435\u0440\u043d\u0443\u0442\u044c \u0438\u0437 \u043d\u0435\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e:<\/p>\n<pre><code class=\"lua\">for s in io.lines(\"glfw3.h\") do    k,v = s:match(\"#define GLFW_([%w_]+)%s+(%g+)\")    if k and tonumber(v) then print(\"GLFW.\"..k.. \" = \" .. tonumber(v)) end end<\/code><\/pre>\n<p>  \u043d\u0430\u0434\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043f\u0430\u0440\u0441\u0438\u043b \u0435\u0449\u0451 \u0438 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u0440\u043e\u0434\u0435 #define A (B|C).<\/p>\n<h2>Userdata<\/h2>\n<p>  \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u0430\u043c\u044f\u0442\u044c\u044e \u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f\u043c\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f ffi.userdata() \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442 \u043f\u0430\u043c\u044f\u0442\u044c \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b Lua, \u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0438\u0439\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u0430\u043a \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u0432 \u0421 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c\/\u0434\u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c \u0432\/\u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043a\u0443\u0441\u043a\u0430 \u043f\u0430\u043c\u044f\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b Lua.<br \/>  \u0418\u043d\u0434\u0435\u043a\u0441\u0430\u0446\u0438\u044f userdata \u043a\u0430\u043a \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b Lua \u0447\u0435\u0440\u0435\u0437 [] \u043f\u043e\u043a\u0430 \u043d\u0435\u0434\u043e\u0434\u0435\u043b\u0430\u043d\u0430.  <\/p>\n<ul>\n<li>x = ffi.userdata(N) \u0432\u044b\u0434\u0435\u043b\u0438\u0442 N \u0431\u0430\u0439\u0442.<\/li>\n<li>x = ffi.userdata(\u00abqweqweqwe\u00bb), \u0432\u044b\u0434\u0435\u043b\u0438\u0442 \u043f\u0430\u043c\u044f\u0442\u044c \u043f\u043e \u0434\u043b\u0438\u043d\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 +1 \u0434\u043b\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e &#8216;\\0&#8217; \u0438 \u043f\u0440\u043e\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u044b\u043c \u0441\u0442\u0440\u043e\u043a\u0438.<\/li>\n<li>x = ffi.userdata({N,K,M}) \u0432\u044b\u0434\u0435\u043b\u0438\u0442 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0442\u0440\u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f \u0438 \u043f\u043e\u0434 \u043a\u0430\u0436\u0434\u044b\u0439 \u0432\u044b\u0434\u0435\u043b\u0438\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 N,K,M \u0431\u0430\u0439\u0442, \u0442.\u0435. \u0434\u0432\u0443\u0445\u043c\u0435\u0440\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0438\u0437 \u0442\u0440\u0451\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0441 \u0440\u0430\u0437\u043c\u0435\u0440\u0430\u043c\u0438 N, M, K \u0431\u0430\u0439\u0442 \u043a\u0430\u0436\u0434\u044b\u0439.<\/li>\n<li>x = ffi.userdata({\u00abqwe\u00bb, \u00abasdfgh\u00bb}) \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f\u043c\u0438 \u043d\u0430 \u0441\u0442\u0440\u043e\u043a\u0438 \u0438 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u0440\u043e\u043a.<\/li>\n<li>x:int(), x:uint(), x:float(), x:double(), x:boolean(), x:string(), \u0434\u0435\u043b\u0430\u044e\u0442 *(int*)x, *(float*)x, *(double*)x \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 \u0432 Lua \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/li>\n<li>x:pack(fmt, v1, v2, &#8230;) \u2014 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0447\u0442\u043e string.pack(fmt, v1, v2, &#8230;), \u0437\u0430\u043f\u0438\u0448\u0435\u0442 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043d\u0430\u0447\u0430\u043b\u043e \u0441\u0442\u0440\u043e\u043a\u0438.<\/li>\n<li>x:unpack(fmt [, pos]) == string.unpack(fmt, x:string() [, pos]) \u2014 \u0440\u0430\u0441\u043f\u0430\u043a\u0443\u0435\u0442 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 pos.<\/li>\n<\/ul>\n<p>  <\/p>\n<h2>\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f OpenGL<\/h2>\n<p>  \u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0441\u0430\u0445\u0430\u0440\u0430 \u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u00ab\u043b\u0435\u043d\u0438\u0432\u0443\u044e\u00bb \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, OpenGL \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0434\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0435 gl \u043c\u0435\u0442\u0430\u0442\u0430\u0431\u043b\u0438\u0446\u0443, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0435\u0449\u0451 \u043d\u0435\u0442 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 gl (\u043c\u0435\u0442\u0430\u043c\u0435\u0442\u043e\u0434 __index \u043a\u0430\u043a \u0440\u0430\u0437 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043a\u043e\u0433\u0434\u0430 \u043f\u043e \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u043a\u043b\u044e\u0447\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442), \u043e\u043d\u0430 \u0431\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u043b\u0430\u0441\u044c \u0438\u0437 opengl32.dll, \u0435\u0441\u043b\u0438 \u0442\u0430\u043c \u0442\u0430\u043a\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432\u0434\u0440\u0443\u0433 \u043d\u0435\u0442, \u0442\u043e \u0447\u0435\u0440\u0435\u0437 wglGetProcAddress, \u043d\u0443 \u0438\u043b\u0438 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u0430\u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f __lib_error (\u0438\u0437 \u043c\u0435\u0442\u0430\u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0436\u0435, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0437\u0430\u0433\u0440\u044f\u0437\u043d\u044f\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443 gl), \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0432\u0430\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439, \u0435\u0441\u043b\u0438 \u043a\u0430\u043a\u0443\u044e-\u043d\u0438\u0431\u0443\u0434\u044c \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c.<\/p>\n<pre><code class=\"lua\">gl.GetProcAddress = ffi(\"opengl32\", \"wglGetProcAddress\", \"ps\") local mt = getmetatable(gl) or {} mt.__index = function(t, k)   t[k] = ffi(\"opengl32\", \"gl\"..k) or ffi(t.GetProcAddress(\"gl\"..k)) or getmetatable(t).__lib_error(t, \"gl\"..k)   return t[k] end mt.__lib_error = function (t, name) error(\"Unable to load '\"..name..\"' from opengl32.dll or wglGetProcAddress\") end setmetatable(mt)<\/code><\/pre>\n<p>  <\/p>\n<h2>\u041b\u0435\u043d\u0438\u0432\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/h2>\n<p>  \u041f\u043e\u0445\u043e\u0436\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0432\u0435\u0434\u0435\u0442 \u0441\u0435\u0431\u044f \u0438 \u0441\u0430\u043c\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 ffi. \u0415\u0441\u043b\u0438 \u0435\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u043c\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438\u043b\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0441\u043e \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u0431\u0435\u0437 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0442\u043e \u043e\u043d\u0430 \u0432\u0435\u0440\u043d\u0451\u0442 \u043f\u0443\u0441\u0442\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0441 \u043c\u0435\u0442\u0430\u043c\u0435\u0442\u043e\u0434\u043e\u043c __index, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0438 \u043a \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u043e\u0438\u0449\u0435\u0442 \u0435\u0451 \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0445 \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u0438, \u0435\u0441\u043b\u0438 \u043d\u0430\u0439\u0434\u0451\u0442, \u2014 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442. \u0427\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0437\u0430\u0434\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0438 \u043f\u043e\u0442\u043e\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0440\u044f\u043c\u0443\u044e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043f\u043e \u0438\u043c\u0435\u043d\u0438 \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u043b\u043e\u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0439<\/p>\n<pre><code class=\"lua\">libs = ffi({\"user32\", \"msvcrt\", \"kernel32\"}) libs.MessageBoxA(0,\"Message\",\"Caption\",0)<\/code><\/pre>\n<p>  <\/p>\n<h2>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u041e\u041e\u041f<\/h2>\n<p>  \u0412 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 GLFW \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0432\u0438\u0434\u0430 glfwXXX(GLFWwindow * w, &#8230;).<br \/>  \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e glfw.CreateWindow(), \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u043b\u0430 \u00ab\u043a\u043b\u0430\u0441\u0441\u00bb \u043e\u043a\u043d\u0430 \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u044d\u0442\u0438\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043d\u0430\u0434\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c GLFWwindow \u043f\u0435\u0440\u0432\u044b\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c.<\/p>\n<pre><code class=\"lua\">local create_window = glfw.CreateWindow function glfw.CreateWindow(...) return setmetatable({window = create_window(...)}, {__index = function(t,k) return function(self,...) return glfw[k](self.window,...) end end }) end<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c glfw.CreateWindow \u0432\u043c\u0435\u0441\u0442\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f \u0432\u0435\u0440\u043d\u0451\u0442 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0441 \u043c\u0435\u0442\u0430\u043c\u0435\u0442\u043e\u0434\u043e\u043c __index \u0438 \u043c\u043e\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"lua\">window = glfw.CreateWindow(...) window:MakeContextCurrent() window:SetKeyCallback(key_callback)<\/code><\/pre>\n<p>  <\/p>\n<h2>Hello glfw window<\/h2>\n<p>  \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440 glfw \u00abhello window\u00bb \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u0434\u044f\u0434\u0435\u0442\u044c \u043a\u0430\u043a-\u0442\u043e \u0442\u0430\u043a:  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">Hello window<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"lua\">local ffi = require(\"ffi\") local gl = require (\"gl\") local glfw = require (\"glfw\") local GL = gl.GL local GLFW = glfw.GLFW  glfw.Init() local window = glfw.CreateWindow(640, 480, \"Simple example\", 0, 0) window:MakeContextCurrent()  local key_callback = function(window, key, scancode, action, mods)   if (key == GLFW.KEY_ESCAPE and action == GLFW.PRESS) then glfw.SetWindowShouldClose(window, GLFW.TRUE) end end key_callback = ffi(key_callback, \"vpiiii\") window:SetKeyCallback(key_callback)    local vs = gl.shader(GL.VERTEX_SHADER, [[#version 150 in vec2 p;  void main(void){ gl_Position = vec4(p.xy, 0.0f, 1.0f); }]])  local fs = gl.shader(GL.FRAGMENT_SHADER, [[#version 150 uniform vec2 resolution; uniform float zoom = 1.0; uniform vec2 pos = vec2(1.25, 0.05); void main(void){   vec2 uv = ((2.0 * gl_FragCoord.xy - resolution) \/ resolution.y) * zoom - pos;   int i = 0;   for (vec2 z = vec2(0.0); (dot(z, z) &lt; 65536.0) &amp;&amp; (i &lt; 100); i++) z = vec2(z.x * z.x - z.y * z.y, 2.0 * z.x * z.y) + uv;   gl_FragColor = vec4(vec3(sin(i * 0.05)) * vec3(0.5, 1.0, 1.3), 1.0); }]])  local prog = gl.program(fs, vs) local pwidth, pheight  = ffi.userdata(4), ffi.userdata(4)  --allocate 4 byte userdata in lua to pass as pointer to C function  gl.ClearColor(0.3, 0.4, 0.5, 1.0)  while window:WindowShouldClose() == GLFW.FALSE do   window:GetFramebufferSize(pwidth, pheight)   local w,h = pwidth:int(), pheight:int()   --dereference userdata pointer to integer, same as pwidth:upack(\"I4\")   gl.Viewport(0, 0, w, h)       prog.resolution = {w, h}          --GLSL uniforms by name with __index\/__newindex of prog, type convertion inside   prog.zoom = math.exp(-5+5*math.cos(os.clock()))   gl.Clear(GL.COLOR_BUFFER_BIT)   gl.Rects(-1,-1,1,1)   window:SwapBuffers()   glfw.PollEvents() end  window:DestroyWindow() glfw.Terminate()<\/code><\/pre>\n<\/div><\/div>\n<p>  \u0412 gl.lua \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u044b \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438\/\u043a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u043a\u0438 \u0448\u044d\u0439\u0434\u0435\u0440\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0441\u0442\u0443\u043f \u043a uniform \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e \u0438\u043c\u0435\u043d\u0438 \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0442\u0430\u043c\u0435\u0442\u043e\u0434 \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u0446\u0438\u0438.<br \/>  <a href=\"https:\/\/github.com\/pavel212\/uffi\/tree\/master\/example\" rel=\"nofollow noopener noreferrer\">https:\/\/github.com\/pavel212\/uffi\/tree\/master\/example<\/a><\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/mm\/lo\/zl\/mmlozlxorxk1ujfriu08898nkpq.png\" alt=\"fractal\" data-src=\"https:\/\/habrastorage.org\/webt\/mm\/lo\/zl\/mmlozlxorxk1ujfriu08898nkpq.png\"\/><\/p>\n<p>  <\/p>\n<h1><i>\u00ab\u041c\u0438\u0448\u043a\u0430 \u0441\u0432\u0435\u0440\u0445\u0443 \u0432\u0435\u0441\u044c \u0438\u0437 \u043f\u043b\u044e\u0448\u0430, \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u0447\u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0438?\u00bb<\/i><\/h1>\n<p>  \u041e\u0431\u044b\u0447\u043d\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u0437 Lua \u043f\u043e\u0437\u0432\u0430\u0442\u044c \u043a\u0430\u043a\u0443\u044e-\u043d\u0438\u0431\u0443\u0434\u044c C \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440<\/p>\n<pre><code class=\"cpp\">int cfunc(const char *, double);<\/code><\/pre>\n<p>  \u043d\u0430\u0434\u043e \u0434\u043b\u044f \u043d\u0435\u0451 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043e\u0431\u0435\u0440\u0442\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 Lua, \u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 \u0432 Lua (\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043f\u043e\u043b\u043e\u0436\u0438\u043b\u0438 \u043d\u0430 Lua \u0441\u0442\u044d\u043a).<\/p>\n<pre><code class=\"cpp\">int luacfunc(lua_State * L){   const char * arg1 = lua_tostring(L, 1);   double       arg2 = lua_tonumber(L, 2);   int ret = cfunc(arg1, arg2);   lua_pushinteger(L, ret);   return 1; }<\/code><\/pre>\n<p>  \u0422\u043e \u0435\u0441\u0442\u044c, \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0441\u043e \u0441\u0442\u044d\u043a\u0430 Lua, \u043f\u043e\u0437\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0437\u0430\u0442\u0435\u043c \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043d\u0430 Lua \u0441\u0442\u044d\u043a \u0442\u043e, \u0447\u0442\u043e \u0432\u0435\u0440\u043d\u0443\u043b\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u0438 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439. \u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 \u0421 \u043e\u0431\u044b\u0447\u043d\u043e \u0438\u043c\u0435\u044e\u0442 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u0436\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043f\u043e\u0437\u0432\u0430\u0442\u044c \u043a\u0430\u043a\u0443\u044e-\u043d\u0438\u0431\u0443\u0434\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0438\u0437 .dll, \u043d\u043e \u0442\u0438\u043f\u044b \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0442\u043e \u043a\u043e\u0434 \u0432\u044b\u0448\u0435\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u0445\u043e\u0434\u0443.<\/p>\n<p>  \u041d\u0430 \u0430\u0441\u0441\u0435\u043c\u0431\u043b\u0435\u0440\u0435 \u044d\u0442\u0430 \u0436\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043a\u0430\u043a-\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"plaintext\">;int luacfunc(lua_State * L){ ;prologue   push 'nonvolatile regs'   sub rsp, NSTACK    ;reserve and align stack  ;const char * arg1 = lua_tostring(L, 1);   mov rcx, L   mov rdx, 1   mov r8, 0   call lua_tolstring         ;#define to_tostring(L,idx) lua_tolstring(L,idx,0)   mov [rsp+ARG1], rax               ;store arg1 on stack  ;double       arg2 = lua_tonumber(L, 2);   mov rcx, L   mov rdx, 2   call lua_tonumber   mov [rsp+ARG2], xmm0              ;store arg2 on stack  ;int ret = cfunc(arg1, arg2);   mov rcx, [rsp+ARG1]               ;load arg1   mov xmm1, [rsp+ARG2]              ;load arg2   call cfunc  ;lua_pushinteger(L, ret);   mov rcx, L   mov rdx, rax               ;cfunc() returned integer value in rax -> as second argument for lua_push in rdx   call lua_pushinteger  ;epilogue   add rsp, NSTACK   ;restore stack   pop 'nonvolatile regs'  ;return 1   mov eax, 1   ret <\/code><\/pre>\n<p>  \u041a\u0430\u043a \u044d\u0442\u043e \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0430 \u0430\u0441\u0441\u0435\u043c\u0431\u043b\u0435\u0440\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 objdump -d, \u0438\u043b\u0438 \u0442\u0443\u0442 <a href=\"https:\/\/godbolt.org\/z\/ec6q4h5dT\" rel=\"nofollow noopener noreferrer\">godbolt.org\/z\/ec6q4h5dT<\/a><\/p>\n<p>  \u0412 \u0434\u0432\u0443\u0445 \u0441\u043b\u043e\u0432\u0430\u0445 \u043f\u0440\u043e <a href=\"https:\/\/learn.microsoft.com\/en-us\/cpp\/build\/x64-calling-convention\" rel=\"nofollow noopener noreferrer\">\u0441\u043e\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u0435 \u043e \u0432\u044b\u0437\u043e\u0432\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0432 Win_x64<\/a>:  <\/p>\n<ul>\n<li>\u043f\u0435\u0440\u0432\u044b\u0435 4 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0432 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0445 rcx\/rdx\/r8\/r9 \u0438\u043b\u0438 xmm0\/xmm1\/xmm2\/xmm3 \u0434\u043b\u044f \u043f\u043b\u0430\u0432\u0430\u044e\u0449\u0435\u0439 \u0437\u0430\u043f\u044f\u0442\u043e\u0439, \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 \u0441\u0442\u044d\u043a.<\/li>\n<li>\u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 rax\/xmm0.<\/li>\n<li>\u0432\u0441\u0451 \u0447\u0442\u043e \u043f\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0443 \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u043d\u0435 \u0432\u043b\u0430\u0437\u0438\u0442 \u0432 8 \u0431\u0430\u0439\u0442 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430 \u2014 \u0447\u0435\u0440\u0435\u0437 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c.<\/li>\n<li>\u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0434\u043e \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u0441\u0442\u044d\u043a\u0435 \u0445\u043e\u0442\u044f \u0431\u044b 32 \u0431\u0430\u0439\u0442\u0430 \u0434\u043b\u044f \u0447\u0435\u0442\u044b\u0440\u0451\u0445 \u043f\u0435\u0440\u0432\u044b\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0438\u0445 \u043c\u0435\u043d\u044c\u0448\u0435 \u0438 \u043d\u0435 \u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u043e\u043d\u0438 \u0447\u0435\u0440\u0435\u0437 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u044b.<\/li>\n<li>\u0441\u0442\u044d\u043a \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0430\u0434\u043e \u0431\u044b \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u043f\u043e 16 \u0431\u0430\u0439\u0442\u0430\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 call, \u043f\u043e\u043b\u043e\u0436\u0438\u043b \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430 \u0441\u0442\u044d\u043a \u0430\u0434\u0440\u0435\u0441 \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u0432 \u0440\u0430\u0437\u043c\u0435\u0440\u0435 8 \u0431\u0430\u0439\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0442\u044d\u043a \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043f\u043e 16 \u0431\u0430\u0439\u0442\u0430\u043c \u043d\u0435 \u0432\u044b\u0440\u043e\u0432\u043d\u0435\u043d.<\/li>\n<\/ul>\n<p>  \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043b\u0438\u0448\u044c \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u044d\u0442\u043e\u0442 \u043f\u0441\u0435\u0432\u0434\u043e\u0430\u0441\u0441\u0435\u043c\u0431\u043b\u0435\u0440\u043d\u044b\u0439 \u043a\u043e\u0434 \u0432 \u0432\u0435\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043c\u0430\u043a\u0440\u043e\u0441\u044b \u0432\u0438\u0434\u0430:<\/p>\n<pre><code class=\"cpp\">#define _push_rbx(p)           _B(p, 0x53) #define _pop_rbx(p)            _B(p, 0x5B) #define _mov_rbx_rcx(p)        _B(p, 0x48, 0x89, 0xCB) #define _sub_rsp_DW(p,x)       _B(p, 0x48, 0x81, 0xEC, _DW(x)) #define _ld_xmm0(p,x)          _B(p, 0xF3, 0x0F, 0x7E, 0x84, 0x24, _DW(x))<\/code><\/pre>\n<p>  \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0438\u0448\u0443\u0442 \u0432 \u043f\u0430\u043c\u044f\u0442\u044c \u043c\u0430\u0448\u0438\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0442\u0438\u043f\u044b \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 lua_to* \/ lua_push*.<\/p>\n<p>  \u041f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0430 \u043c\u0430\u043a\u0440\u043e\u0441\u0430 _B \u043f\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0431\u0430\u0439\u0442 \u043f\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044e, (\u0441 \u043a\u043e\u0441\u0442\u044b\u043b\u044f\u043c\u0438 \u0434\u043b\u044f msvc, \u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0441\u0432\u043e\u0435\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u043d\u0430 \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435 \u043c\u0430\u043a\u0440\u043e\u0441\u043e\u0432), \u0430 \u0442\u0430\u043a\u0436\u0435 \u043c\u0430\u043a\u0440\u043e\u0441\u044b _DW, _QW \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0441\u043b\u043e\u0432 \u0446\u0435\u043b\u0438\u043a\u043e\u043c, \u043d\u043e \u043d\u043e\u0433\u0430\u043c\u0438 \u0432\u043f\u0435\u0440\u0451\u0434.  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0421\u0442\u0440\u0430\u0448\u043d\u043e, \u043e\u0447\u0435\u043d\u044c \u0441\u0442\u0440\u0430\u0448\u043d\u043e<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">#define _ARGN(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,...) A17 #define _ARGC(...) _EXPAND_MSVC(_ARGN(__VA_ARGS__,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)) #define _EXPAND_MSVC(x) x #define _B(x,...) _EXPAND_MSVC(_ARGN(__VA_ARGS__,B16,_B15,_B14,_B13,_B12,_B11,_B10,_B09,_B08,_B07,_B06,_B05,_B04,_B03,_B02,_B01) (x,__VA_ARGS__)) #define _B01(x,A)                               ( *(uint8_t*)x++ = (uint8_t)A, x) #define _B02(x,A,B)                             ( _B01(x,A),                             _B01(x,B) ) #define _B03(x,A,B,C)                           ( _B02(x,A,B),                           _B01(x,C) ) #define _B04(x,A,B,C,D)                         ( _B03(x,A,B,C),                         _B01(x,D) ) #define _B05(x,A,B,C,D,E)                       ( _B04(x,A,B,C,D),                       _B01(x,E) ) #define _B06(x,A,B,C,D,E,F)                     ( _B05(x,A,B,C,D,E),                     _B01(x,F) ) #define _B07(x,A,B,C,D,E,F,G)                   ( _B06(x,A,B,C,D,E,F),                   _B01(x,G) ) #define _B08(x,A,B,C,D,E,F,G,H)                 ( _B07(x,A,B,C,D,E,F,G),                 _B01(x,H) ) #define _B09(x,A,B,C,D,E,F,G,H,I)               ( _B08(x,A,B,C,D,E,F,G,H),               _B01(x,I) ) #define _B10(x,A,B,C,D,E,F,G,H,I,J)             ( _B09(x,A,B,C,D,E,F,G,H,I),             _B01(x,J) ) #define _B11(x,A,B,C,D,E,F,G,H,I,J,K)           ( _B10(x,A,B,C,D,E,F,G,H,I,J),           _B01(x,K) ) #define _B12(x,A,B,C,D,E,F,G,H,I,J,K,L)         ( _B11(x,A,B,C,D,E,F,G,H,I,J,K),         _B01(x,L) ) #define _B13(x,A,B,C,D,E,F,G,H,I,J,K,L,M)       ( _B12(x,A,B,C,D,E,F,G,H,I,J,K,L),       _B01(x,M) ) #define _B14(x,A,B,C,D,E,F,G,H,I,J,K,L,M,N)     ( _B13(x,A,B,C,D,E,F,G,H,I,J,K,L,M),     _B01(x,N) ) #define _B15(x,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O)   ( _B14(x,A,B,C,D,E,F,G,H,I,J,K,L,M,N),   _B01(x,O) ) #define _B16(x,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P) ( _B15(x,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O), _B01(x,P) )  #define _DW(x) x, (x)>>8, (x)>>16, (x)>>24 #define _QW(x) x, (x)>>8, (x)>>16, (x)>>24, (x)>>32, (x)>>40, (x)>>48, (x)>>56<\/code><\/pre>\n<\/div><\/div>\n<p>  \u0421\u043e\u0432\u0441\u0435\u043c \u0431\u0435\u0437 \u043c\u0430\u043a\u0440\u043e\u0441\u043e\u0432 \u0432 \u0421, \u043f\u043e\u0436\u0430\u043b\u0443\u0439, \u043d\u0435 \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043f\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u0430\u0440\u0433\u043c\u0435\u043d\u0442\u043e\u0432, \u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043a\u0440\u0430\u0441\u0438\u0432\u0435\u0435 \u0438 \u043f\u043e\u043d\u0430\u0434\u0435\u044f\u0442\u044c\u0441\u044f \u043d\u0430 \u0432\u043c\u0435\u043d\u044f\u0435\u043c\u043e\u0441\u0442\u044c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430, \u0447\u0442\u043e \u043e\u043d \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043e\u0433\u0430\u0434\u043b\u0438\u0432\u044b\u0439, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0434\u0451\u0440\u0433\u0430\u0442\u044c \u043a\u0430\u0434\u0436\u044b\u0439 \u0440\u0430\u0437 memcpy \u0434\u043b\u044f \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0446\u0435\u043b\u043e\u0433\u043e \u0431\u0430\u0439\u0442\u0430.<\/p>\n<pre><code class=\"cpp\">#define _B(x,...) (memcpy(x, (const uint8_t[]){__VA_ARGS__}, sizeof((uint8_t[]){__VA_ARGS__}) ), (uint8_t*)x += sizeof((uint8_t[]){__VA_ARGS__}))<\/code><\/pre>\n<p>  \u041d\u0435 \u0442\u043e \u0447\u0442\u043e \u0431\u044b \u0431\u044b\u0441\u0442\u0440\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043e\u0434\u0430 \u043e\u0431\u0451\u0440\u0442\u043a\u0438 \u0445\u043e\u0442\u044c \u043d\u0430 \u0447\u0442\u043e-\u0442\u043e \u0432\u043b\u0438\u044f\u043b\u043e, \u043d\u043e \u043a\u043e\u0433\u0434\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0431\u0430\u0439\u0442\u0430 \u0432 \u043f\u0430\u043c\u044f\u0442\u044c \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0442\u0441\u044f \u0432\u044b\u0437\u043e\u0432\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0433\u0434\u0435-\u0442\u043e \u0433\u0440\u0443\u0441\u0442\u0438\u0442 \u043e\u0434\u0438\u043d \u043a\u043e\u0442\u0438\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0435\u0449\u0451 \u043d\u0435 \u0437\u043d\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u0442\u043e \u043f\u043b\u043e\u0445\u043e. \u0422\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 msvc \u0441\u043f\u0440\u0430\u0432\u0438\u043b\u0441\u044f \u0438 \u0434\u0430\u0436\u0435 \u0434\u0432\u0430 \u0438\u0434\u0443\u0449\u0438\u0445 \u043f\u043e\u0434\u0440\u044f\u0434 \u043c\u0430\u043a\u0440\u043e\u0441\u0430<\/p>\n<pre><code class=\"cpp\">_push_rbx(p); _mov_rbx_rcx(p);<\/code><\/pre>\n<p>  \u0440\u0430\u0437\u0432\u0451\u0440\u043d\u0443\u0442\u044b\u0435 \u043f\u0440\u0435\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043e\u043c \u0432<\/p>\n<pre><code class=\"cpp\">(memcpy(p, (const uint8_t[]){0x53}, sizeof((uint8_t[]){0x53}) ), (uint8_t*)p += sizeof((uint8_t[]){0x53}));         (memcpy(p, (const uint8_t[]){0x48, 0x89, 0xCB}, sizeof((uint8_t[]){0x48, 0x89, 0xCB}) ), (uint8_t*)p += sizeof((uint8_t[]){0x48, 0x89, 0xCB})); <\/code><\/pre>\n<p>  \u0431\u044b\u043b\u0438 \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0432\u043c\u0435\u0441\u0442\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0432 \u043e\u0434\u043d\u0443 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044e mov, \u043c\u0435\u043b\u043e\u0447\u044c \u0430 \u043f\u0440\u0438\u044f\u0442\u043d\u043e.<\/p>\n<pre><code class=\"cpp\">00037    c7 01 53 48 89 cb      mov DWORD PTR [rcx], -880195501 ; cb894853H<\/code><\/pre>\n<p>  \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0430\u0441\u044c \u0432\u043e\u0442 \u0442\u0430\u043a\u0430\u044f \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043c\u0435\u0448\u0430\u043d\u0438\u043d\u0430 \u0438\u0437 \u0421 \u0438 \u043f\u0441\u0435\u0432\u0434\u043e\u0430\u0441\u0441\u0435\u043c\u0431\u043b\u0435\u0440\u0430, \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0449\u0430\u044f \u043c\u0430\u0448\u0438\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u043e\u0431\u0451\u0440\u0442\u043a\u0438 \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u0421 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u0437 Lua.<\/p>\n<pre><code class=\"cpp\">int make_func(char * code, void * func, const char * argt){   int argc = strlen(argt);   int stack = 16 * ((argc + 4)>>1);  \/\/32 bytes of shadow space + space for function arguments multiple of 16 bytes to keep stack alignment   char * p = code;  { \/\/prologue     _push_rbx(p);        \/\/additional push rbx makes stack aligned to 16.     _mov_rbx_rcx(p);         \/\/as we are in luaCfunction: int f(lua_State * L); L is passed in rcx. store lua_State * L in rbx,     _sub_rsp_DW(p,stack);   \/\/reserve stack  \/\/get arguments from lua stack and store them on stack     for (int i = 1; i &lt; argc; i++){  \/\/argt[0] - return type       _mov_rcx_rbx(p);        \/\/first argument lua_State * L        _mov_rdx_DW(p, i+1);  \/\/second argument n+1 - position of argument on lua stack, [1] == self, [2] == first arg, ...       _clr_r8(p);         \/\/some lua_to functions could have 3rd argument, #define lua_tostring(L, i) lua_tolstring(L, i, 0)       _call(p, lua_to(argt[i]));       if (argt[i] == 'f') _mov_xmm0f_xmm0(p);                                                            \/\/double -> float conversion, double lua_tonumber();       if (argt[i] == 'f' || argt[i] == 'd') _st_xmm0(p, 24+i*8); else _st_rax(p, 24+i*8);    \/\/store argument on stack with 32 bytes offset of shadow store     }      _add_rsp_DW(p, 32);    \/\/adjust stack by shadow 32 bytes that were reserved for lua_to functions, so other (4+) arguments on stack with a proper offset  \/\/put back first four arguments to registers     if (argc > 1){ if (argt[1] == 'f' || argt[1] == 'd') _ld_xmm0(p, 0);  else _ld_rcx(p, 0);  }     if (argc > 2){ if (argt[2] == 'f' || argt[2] == 'd') _ld_xmm1(p, 8);  else _ld_rdx(p, 8);  }     if (argc > 3){ if (argt[3] == 'f' || argt[3] == 'd') _ld_xmm2(p, 16); else _ld_r8 (p, 16); }     if (argc > 4){ if (argt[4] == 'f' || argt[4] == 'd') _ld_xmm3(p, 24); else _ld_r9 (p, 24); }      _call(p, func);  \/\/lua_push() function to put return value onto lua stack     _mov_rcx_rbx(p);                                      \/\/first argument lua_State * L      if      (argt[0] == 'f') _mov_xmm1_xmm0f(p);          \/\/convert float to double and mov return value(xmm0) to (xmm1) second argument  of lua_push     else if (argt[0] == 'd') _mov_xmm1_xmm0(p);           \/\/mov double without conversion     else _mov_rdx_rax(p);                                 \/\/other types returned in rax -> second argument in rdx     _clr_r8(p);                                       \/\/some lua_push functions could have 3rd argument     _call(p, lua_push(argt[0])); \/\/return 1     _mov_rax_DW(p, 1);                                    \/\/return 1, even void func() returns 1 and lua_pushnil just for uniformity.     _add_rsp_DW(p, stack-32);                              \/\/restore stack pointer     _pop_rbx(p);                                        \/\/and rbx     _ret(p);   }   return p - code;             \/\/length of generated code }<\/code><\/pre>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 lua_to \/ lua_push \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u0442\u0438\u043f\u0430<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">void * lua_to  (const char t){    switch (t){     case 'v': return voidfunc;        \/\/do nothing: void voidfunc() {}     case 'i': return lua_tointegerx;     case 'f': return lua_tonumberx;     case 'd': return lua_tonumberx;     case 'b': return lua_toboolean;     case 's': return lua_tolstring;     case 'p': return luaF_topointer;  \/\/lua_tointeger || lua_touserdata     case 't': return luaF_totable;     default : return voidfunc;   }   return voidfunc; }<\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  \u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438 \u043a\u0443\u0441\u043e\u043a \u043a\u043e\u0434\u0430 \u043d\u0430\u0434\u043e \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435<\/p>\n<pre><code class=\"cpp\">  DWORD protect;   VirtualProtect(code, size, PAGE_EXECUTE_READWRITE, &amp;protect);<\/code><\/pre>\n<p>  \u0421\u0430\u043c \u043a\u043e\u0434 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 Lua \u043a\u0430\u043a userdata, \u0438 \u0447\u0442\u043e\u0431\u044b \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043a\u0430\u043a Lua \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043d\u0430\u0434\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0435\u043c\u0443 \u043c\u0435\u0442\u0430\u043c\u0435\u0442\u043e\u0434 __call, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u044c\u043c\u0451\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0441\u0430\u043c\u043e\u0433\u043e \u0441\u0435\u0431\u044f \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 (\u0432 \u043c\u0435\u0442\u0430\u043c\u0435\u0442\u043e\u0434\u044b \u043f\u0435\u0440\u0432\u044b\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u0441\u0430\u043c \u043e\u0431\u044a\u0435\u043a\u0442 self) \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u0437\u043e\u0432\u0435\u0442 \u0435\u0433\u043e \u043a\u0430\u043a \u0444\u0443\u043d\u043a\u0446\u0438\u044e.<\/p>\n<pre><code class=\"cpp\">int __call(lua_State * L){    int (*f)(lua_State*) = lua_touserdata(L, 1);    return f ? f(L) : 0;  }<\/code><\/pre>\n<p>  \u043c\u043c\u043c, \u0411 \u2014 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u043a\u043e\u0434: \u00ab\u043d\u0430\u043c \u0442\u0443\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0438 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c, \u0430 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043f\u043e \u043d\u0435\u043c\u0443 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043a\u043e\u0434\u00bb, \u043d\u0443 \u0445\u043e\u0442\u044f \u0431\u044b \u043d\u0430 0 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043b\u0438.<\/p>\n<p>  \u0410 \u0432 \u00ab\u0434\u0435\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440e\u00bb __gc, \u0432 \u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442, \u043a\u043e\u0433\u0434\u0430 \u044d\u0442\u0443 \u043e\u0431\u0451\u0440\u0442\u043a\u0443 \u0443\u0436\u0435 \u043f\u0440\u0438\u0448\u0435\u043b \u0437\u0430\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u0431\u043e\u0440\u0449\u0438\u043a \u043c\u0443\u0441\u043e\u0440\u0430, \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043e\u0434\u043d\u043e \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0443\u0431\u0440\u0430\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441 \u044d\u0442\u043e\u0433\u043e \u043a\u0443\u0441\u043a\u0430 \u043f\u0430\u043c\u044f\u0442\u0438. \u0418 \u0440\u0430\u0437\u043b\u043e\u0436\u0438\u0442\u044c, \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c, \u0437\u0434\u0435\u0441\u044c \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0433\u0440\u0430\u0431\u043b\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0430\u043c\u044f\u0442\u044c \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442 lua_newuserdata \u043a\u0430\u043a \u043f\u043e\u043f\u0430\u043b\u043e, \u0430 VirtualProtect \u043e\u043f\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c\u0438 (~4\u043a\u0411), \u0442\u043e, \u0441\u043d\u044f\u0432, \u043f\u0440\u0438 \u0443\u043d\u0438\u0447\u043d\u043e\u0436\u0435\u043d\u0438\u0438, \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441 \u043e\u0434\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0437\u0430\u043e\u0434\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u0437\u0430\u043f\u0440\u0435\u0442\u0438\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0438 \u0434\u0440\u0443\u0433\u0438\u043c, \u043f\u043e\u043a\u0430 \u0435\u0449\u0451 \u0436\u0438\u0432\u044b\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c, \u043a \u0438\u0445 \u043d\u0435\u0441\u0447\u0430\u0441\u0442\u044c\u044e, \u043f\u043e\u043f\u0430\u0432\u0448\u0438\u043c \u0432 \u044d\u0442\u0438 \u0436\u0435 4\u043a\u0411. \u0422\u043e \u0435\u0441\u0442\u044c \u043d\u0430\u0434\u043e \u043b\u0438\u0431\u043e \u0441\u0430\u043c\u043e\u043c\u0443 \u0432\u044b\u0434\u0435\u043b\u044f\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c, \u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u043e\u043c \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u0443\u0441\u043a\u0435 (\u043f\u043e\u0434\u043c\u0435\u043d\u044f\u0442\u044c \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u043d\u0430 \u0441\u0432\u043e\u0439 \u0447\u0435\u0440\u0435\u0437 lua_setallocf), \u0438\u043b\u0438 \u0432\u044b\u0434\u0435\u043b\u044f\u0442\u044c \u043f\u043e 4\u043a\u0411 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043d\u0430 \u043a\u0430\u0436\u0434\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043b\u0438\u0431\u043e \u0433\u043e\u0440\u043e\u0434\u0438\u0442\u044c \u043f\u043e\u0434\u0441\u0447\u0451\u0442 \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b. \u0418\u043b\u0438 \u0436\u0435, \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044f\u0441\u044c \u0440\u0430\u043d\u0435\u0435 \u043f\u0440\u0438\u043d\u044f\u0442\u043e\u0439 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u0434\u0430, \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u0441\u043b\u0435 \u0441\u0435\u0431\u044f \u043a\u0443\u0441\u043a\u0438 \u043f\u0430\u043c\u044f\u0442\u0438 \u0441 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430.<\/p>\n<p>  \u041f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u043d\u0430 \u043a\u0430\u0436\u0434\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0438\u0437 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u043b\u0430\u0441\u044c LoadLibrary, \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u044f \u0435\u0451 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u0441\u0447\u0451\u0442\u0447\u0438\u043a, \u0442\u0430\u043a \u0447\u0442\u043e \u0432\u044b\u0437\u043e\u0432 FreeLibrary \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0435 \u0437\u0430\u043a\u0440\u043e\u0435\u0442 \u044d\u0442\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445.<\/p>\n<p>  \u0423\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u043c\u043e\u0436\u043d\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 uservalue. \u041a \u043a\u0430\u0436\u0434\u044b\u043c userdata \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044f\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0438\u0437 \u0421 \u0447\u0435\u0440\u0435\u0437 lua_getiuservalue.<\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">__gc<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">int __gc(lua_State * L){   lua_getiuservalue(L, 1, 1);   FreeLibrary(lua_touserdata(L, -1));   lua_pop(L, 1);   DWORD protect;   VirtualProtect(lua_touserdata(L, 1), lua_rawlen(L, 1), PAGE_READWRITE, &amp;protect);   return 0; }<\/code><\/pre>\n<\/div><\/div>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u0430\u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0438\u0437 \u0421<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">  lua_newtable(L, 0, 2);   lua_pushcfunction(L, __gc);   lua_setfield(L, -2, \"__gc\");   lua_pushcfunction(L, __call);   lua_setfield(L, -2, \"__call\");   lua_setmetatable(L, -2);<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h2>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432<\/h2>\n<p>  \u0415\u0441\u043b\u0438 \u0442\u0438\u043f\u044b \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u043d\u044b \u044f\u0432\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0443\u0433\u0430\u0434\u0430\u0442\u044c \u0438\u0445 \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0442\u0438\u043f\u043e\u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 Lua \u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0443\u0436\u0435 \u0432 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u0434\u0435 \u0434\u0435\u0433\u0440\u0430\u0442\u044c Lua \u043f\u043e \u0432\u043e\u043f\u0440\u043e\u0441\u0430\u043c \u0442\u0438\u043f\u043e\u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0442.\u0435. \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0430 \u043d\u0435 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u00ab\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438\u00bb, \u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u0435\u0440\u0435\u043b\u043e\u0436\u0438\u0442\u044c \u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0437\u0430\u0431\u043e\u0442\u0443 \u043e \u0442\u0438\u043f\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0435\u0433\u043e \u0432 \u043d\u0430\u0434\u043b\u0435\u0436\u0430\u0449\u0438\u0439 \u0434\u043b\u044f Lua \u0432\u0438\u0434, \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0442\u0434\u0430\u0432 \u0435\u043c\u0443 \u043e\u0431\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430 \u0438 \u0446\u0435\u043b\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0439 rax \u0438 xmm0 \u0441 \u043f\u043b\u0430\u0432\u0430\u044e\u0449\u0435\u0439 \u0437\u0430\u043f\u044f\u0442\u043e\u0439, \u0432 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 (\u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u0438\u043f\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f) \u043f\u0443\u0441\u0442\u044c \u0434\u0435\u043b\u0430\u0435\u0442 \u0441 \u043d\u0438\u043c\u0438 \u0447\u0442\u043e \u0445\u043e\u0447\u0435\u0442.<\/p>\n<p>  \u0417\u0430\u0442\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e \u043f\u0440\u043e \u0442\u0438\u043f\u044b \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u043a\u043e\u0434 \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u0445\u043e\u0434\u0443, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043c\u0435\u0442\u0430\u043c\u0435\u0442\u043e\u0434 __call \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u043d\u0430 \u0447\u0435\u043b\u043e\u0432\u0435\u0447\u0435\u0441\u043a\u043e\u043c \u0430\u0441\u0441\u0435\u043c\u0431\u043b\u0435\u0440\u0435. \u041f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0430 \u0421, \u0447\u0435\u0440\u0435\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044f \u043f\u043e\u043d\u044f\u043b, \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u0442\u0430\u043c \u0432\u0440\u043e\u0434\u0435 \u0431\u044b \u0432\u0441\u044f\u043a\u0438\u0435 \u043d\u0435\u043f\u043e\u0442\u0440\u0435\u0431\u0441\u0442\u0432\u0430, \u0432\u0440\u043e\u0434\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f float->double \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0442. \u0410 \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e, \u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0432\u043a\u0440\u0430\u043f\u043b\u0435\u043d\u0438\u044f\u043c\u0438 \u0430\u0441\u0441\u0435\u043c\u0431\u043b\u0435\u0440\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0445\u0438\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 \u0441\u0442\u044d\u043a \u043f\u0435\u0440\u0435\u0434 \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0442\u043e\u0436\u0435 \u043d\u0435 \u0432\u044b\u0439\u0434\u0435\u0442, \u0442\u0430\u043a \u043a\u0430\u043a msvc \u2014 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0436\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 30 \u043b\u0435\u0442 \u043f\u0438\u043b\u044f\u0442, \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u0439 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u043d\u0430 64 \u0431\u0438\u0442\u0430 \u0432\u0434\u0440\u0443\u0433 \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u0440\u0430\u0437\u0443\u0447\u0438\u043b\u0441\u044f \u0434\u0435\u043b\u0430\u0442\u044c inline assembly.  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">call.asm<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"plaintext\">extrn lua_pushnumber : proc extrn lua_pushinteger: proc extrn lua_touserdata : proc extrn lua_gettop : proc extrn luaF_isfloat : proc extrn luaF_typeto : proc  .code func__call_auto PROC   push rbx   push r12   push r13   push r14   push r15      sub rsp, 32    mov rbx, rcx               ;first argument lua_State * L passed in rcx, store in rbx    mov rdx, 1   call lua_touserdata   mov r15, [rax]             ;store function pointer in r15    mov rcx, rbx   call lua_gettop              mov r12, rax               ;store number of arguments in r12    shr eax, 1   shl eax, 4   sub rsp, rax               ;reserve stack ((n+1)\/2)*16  [1] - self  ;\/\/for (int i = 1; i &lt; argc; i++) arg[i] = arg_to(L, i+1)   xor r13, r13   inc r13 arg_loop:   cmp r13, r12   jge arg_loop_end   inc r13    mov rcx, rbx   mov rdx, r13   call luaF_isfloat   mov r14, rax               ;r14 - arg_isfloat?    mov rcx, rbx   mov rdx, r13   call luaF_typeto                ;get pointer to proper lua_to function     mov rcx, rbx   mov rdx, r13   xor r8, r8   call rax                   ;call lua_to     cmp r14, 0   jz store_int store_float:   movq  QWORD PTR [rsp + r13*8 + 16], xmm0  ;store floating point arg   jmp arg_loop store_int:   mov [rsp + r13*8 + 16], rax               ;store integer arg   jmp arg_loop arg_loop_end:    add rsp, 32  ;load args to registers, both r*x &amp; xmm*, should be faster than checks for floating point \/ integer type ;and loading all 4 args (garbage if &lt;4) probably also faster than checks for actual number of arguments  ;  mov r13, r12  ;  dec r13 ;  jz call_cfunc   mov rcx, [rsp]   movq xmm0, rcx    ;  dec r13 ;  je call_cfunc   mov rdx, [rsp+8]   movq xmm1, rdx  ;  dec r13 ;  jz call_cfunc   mov r8, [rsp+16]   movq xmm2, r8  ;  dec r13 ;  jz call_cfunc   mov r9, [rsp+24]   movq xmm3, r9  call_cfunc:   call r15    movq r14, xmm0    mov rcx, rbx   mov rdx, rax   call lua_pushinteger         ;first return integer    mov rcx, rbx   movq xmm1, r14   call lua_pushnumber          ;then return floating point    shr r12, 1   shl r12, 4   add rsp, r12                 ;restore stack    pop r15   pop r14   pop r13   pop r12   pop rbx    mov eax, 2   ret func__call_auto ENDP END<\/code><\/pre>\n<\/div><\/div>\n<p>  \u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f arg_to, \u043a\u0430\u043a \u0438 lua_to \u0440\u0430\u043d\u0435\u0435, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0441 Lua \u0441\u0442\u044d\u043a\u0430, \u043d\u043e \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 lua_type(L,idx).<\/p>\n<h2>\u0421\u043f\u0438\u0441\u043e\u043a \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u0447\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/h2>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 .dll \u0447\u0435\u0440\u0435\u0437 LoadLibrary, \u0435\u0451 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 LoadLibrary \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442. \u0424\u0443\u043d\u043a\u0446\u0438\u044f dllfuncname \u0441\u043b\u0435\u0433\u043a\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0441\u0438\u043d\u0433\u043d\u0430\u0442\u0443\u0440\u0443 \u0438 \u0442\u0438\u043f, \u0438, \u043f\u043e\u043b\u0430\u0437\u0438\u0432 \u043f\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u043c PE, \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0438\u043c\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<p>  <a href=\"http:\/\/www.openrce.org\/reference_library\/files\/reference\/PE%20Format.pdf\" rel=\"nofollow noopener noreferrer\">\u0417\u0434\u0435\u0441\u044c \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 PE<\/a>, \u043d\u043e \u0434\u043b\u044f x64 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043b\u044f \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u043f\u043e 8 \u0431\u0430\u0439\u0442 \u0438, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 EXPORT_DIRECTORY \u0432 136 \u0431\u0430\u0439\u0442, \u0430 \u043d\u0435 120 \u043a\u0430\u043a \u043d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435.<\/p>\n<p>  \u041e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043c\u0430\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442 \u043a\u0430\u043a \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u043d\u0430\u0434\u043e:<\/p>\n<pre><code class=\"cpp\">const char * dllfuncname(const uint32_t * lib, int idx){   if (lib == 0) return 0;   if (idx &lt; 0) return 0;   const uint32_t * p = lib;   if ((p[0] &amp; 0xFFFF) != 0x5A4D) return 0; \/\/MZ   p = &amp;lib[p[15] >> 2];                    \/\/e_lfanew   if (p[0] != 0x00004550) return 0;        \/\/signature   if ((p[1] &amp; 0xFFFF) != 0x8664) return 0; \/\/machine   p = &amp;lib[p[34] >> 2];                    \/\/EXPORT_DIRECTORY   if (idx >= p[6]) return 0;               \/\/NumberOfNames   p = &amp;lib[(p[8] >> 2) + idx];             \/\/AddressOfNames[idx]     return &amp;((char*)lib)[*p];               }<\/code><\/pre>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u0432\u044b\u0432\u043e\u0434\u0430 \u0441\u043f\u0438\u0441\u043a\u0430 \u0432\u0441\u0435\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u0447\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">void main(int argc, char ** argv){   const char * name = argv[1];   char path[260];   if (SearchPath(NULL, name, \".dll\", sizeof(path), path, 0)) name = path;   HMODULE lib = LoadLibrary(name);   int idx = 0;   while (0 != (name = dllfuncname(lib, idx))) printf(\"%d: %s\\n\", idx++, name);   FreeLibrary(lib); }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h2>Callback<\/h2>\n<p>  \u0414\u043b\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f Lua \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 C callback, \u043d\u0430\u0434\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u043d\u0430 Lua c\u0442\u044d\u043a \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u0430\u043c\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043f\u043e\u0442\u043e\u043c \u0435\u0451 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b, \u0441\u0434\u0435\u043b\u0430\u0442\u044c lua_pcall, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0431\u0435\u0440\u0435\u0442 \u0441\u043e \u0441\u0442\u044d\u043a\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0438 \u0435\u0451 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442 \u0435\u0451, \u0438 \u043f\u043e\u043b\u043e\u0436\u0438\u0442 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0434\u043e \u0437\u0430\u0431\u0440\u0430\u0442\u044c \u0441 Lua \u0441\u0442\u044d\u043a\u0430 \u0438 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0432 \u0421.<\/p>\n<p>  \u0421\u0430\u043c\u0443 Lua \u0444\u0443\u043d\u043a\u0446\u0438\u044e (\u0434\u0430 \u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c lua_State * L) \u043d\u0430\u0434\u043e \u043a\u0430\u043a-\u0442\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u044c C callback \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438 \u0434\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 LUA_REGISTRYINDEX \u2014 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\u0439 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0441\u044b\u043b\u043e\u043a, \u0438 \u043f\u043e\u0442\u043e\u043c \u0437\u0430\u0445\u0430\u0440\u043a\u043e\u0434\u0438\u0442\u044c \u044d\u0442\u0443 \u0441\u0441\u044b\u043b\u043a\u0443, \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 lua_State * L, \u0432 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u043a\u043e\u0434. \u0417\u0430\u043e\u0434\u043d\u043e \u044d\u0442\u043e \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0442\u0438\u0442 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e, \u043a\u043e\u0433\u0434\u0430 \u0441\u0430\u043c\u0443 Lua \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0432\u0434\u0440\u0443\u0433 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u0437\u0430\u0431\u0440\u0430\u043b \u0441\u0431\u043e\u0440\u0449\u0438\u043a \u043c\u0443\u0441\u043e\u0440\u0430 (\u0437\u0430 \u043d\u0435\u043d\u0430\u0434\u043e\u0431\u043d\u043e\u0441\u0442\u044c\u044e), \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043e\u0442 \u043f\u043e\u043a\u0430 \u0435\u0449\u0451 \u0436\u0438\u0432\u043e\u0439 callback \u043e\u0431\u0451\u0440\u0442\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0435\u0451 \u043f\u043e\u0437\u0432\u0430\u0442\u044c, \u043d\u0435 \u0437\u043d\u0430\u044f \u0447\u0442\u043e \u0441\u0430\u043c\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0443\u0436\u0435 \u043d\u0435\u0442.<\/p>\n<p>  \u041f\u0440\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043e\u0434\u0430 \u043e\u0431\u0451\u0440\u0442\u043a\u0438 \u043d\u0430\u0434\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 int funcref = luaL_ref(L, LUA_REGISTRYINDEX), \u0430 \u0432 \u0441\u0430\u043c\u043e\u0439 \u043e\u0431\u0451\u0440\u0442\u043a\u0435 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u0438 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u044d\u0442\u0443 Lua \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043d\u0430 Lua \u0441\u0442\u044d\u043a \u0447\u0435\u0440\u0435\u0437 lua_rawgeti(L, LUA_REGISTRYINDEX, funcref); \u0418 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0434\u043b\u044f \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 (\u0434\u043b\u044f Lua \u044d\u0442\u043e \u043f\u043e \u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 userdata) \u043c\u0435\u0442\u0430\u043c\u0435\u0442\u043e\u0434 __gc, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438 \u0443\u043d\u0438\u0447\u043d\u043e\u0436\u0435\u043d\u0438\u0438 \u043e\u0431\u0451\u0440\u0442\u043a\u0438 \u0437\u0430\u043e\u0434\u043d\u043e \u043f\u043e\u0447\u0438\u0441\u0442\u0438\u0442 \u0441\u0441\u044b\u043b\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 luaL_unref(L, LUA_REGISTRYINDEX, funcref). \u0418 \u043c\u0435\u0442\u0430\u043c\u0435\u0442\u043e\u0434 __call \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0437\u043e\u0432\u0451\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u0443\u044e Lua \u0444\u0443\u043d\u043a\u0446\u0438\u044e.<br \/>  \u0422\u043e \u0435\u0441\u0442\u044c \u043d\u0430\u0434\u043e \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434 \u0434\u043b\u044f:<\/p>\n<pre><code class=\"cpp\">int callback(const char * arg1, double arg2){   lua_rawgeti(L, LUA_REGISTRYINDEX, funcref)   lua_pushstring(L, arg1);   lua_pushnumber(L, arg2);   lua_pcall(L, 2, 1);   return lua_tointeger(L, -1); }<\/code><\/pre>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041e\u0442 \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u0421 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 Lua \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0438\u0430\u043b\u044c\u043d\u043e \u043d\u0435 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f, \u0432\u0441\u0451 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443.<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">int make_cb(char * code, int size, lua_State * L, int ref, const char * argt){   int argc = strlen(argt);   char * p = code; {     _push_rbx(p);     \/\/push rbx to align stack to 16 and store lua_State * L in rbx     _mov_rbx_QW(p, (uintptr_t)L);   \/\/as we are generating ordinary C function, lua_State * L is passed as argument from ffi and stored as immediate constant in code.      if (argc > 1) if (argt[1] == 'f' || argt[1] == 'd') _st_xmm0(p, 16); else _st_rcx(p, 16);  \/\/store 4 arguments in shadow     if (argc > 2) if (argt[2] == 'f' || argt[2] == 'd') _st_xmm1(p, 24); else _st_rdx(p, 24);     if (argc > 3) if (argt[3] == 'f' || argt[3] == 'd') _st_xmm2(p, 32); else _st_r8 (p, 32);     if (argc > 4) if (argt[4] == 'f' || argt[4] == 'd') _st_xmm3(p, 40); else _st_r9 (p, 40);      _sub_rsp_DW(p, 48); \/\/32 shadow space + additional 8 bytes for 5th argument of lua_callk + 8 bytes to keep 16 bytes alignment      _mov_rcx_rbx(p);     _mov_rdx_DW(p, LUA_REGISTRYINDEX);     _mov_r8_DW(p, ref);        \/\/lua function we are going to wrap (ref) as C callback is stored in lua registry, so it is not garbage collected accidentally     _call(p, lua_rawgeti);   \/\/get lua function on stack from registry lua_rawgeti(L, REIGSTRYINDEX, funcref)      for (int i = 1; i &lt; argc; i++){       _mov_rcx_rbx(p);   \/\/first argument lua_State * L        if (argt[i] == 'f' || argt[i] == 'd') _ld_xmm1(p, 56+i*8); else _ld_rdx(p, 56+i*8);           \/\/get second argument for lua_push from stack       if (argt[i] == 'f') _mov_xmm1_xmm1f(p);                                                           \/\/float -> double conversion for lua_pushnumber       _clr_r8(p);     \/\/some lua_push functions have 3rd argument       _call(p, lua_push(argt[i]));     }      _mov_rcx_rbx(p);     _mov_rdx_DW(p, argc-1);     _mov_r8_DW(p, 1);     _clr_r9(p);     _st_r9(p, 32);     _call(p, lua_callk);   \/\/lua_callk(L, argc-1, 1, 0, 0); lua function always return 1 value, nil for void f() callback      _mov_rcx_rbx(p);        \/\/first argument lua_State * L      _mov_rdx_DW(p, -1);   \/\/return value is on top of the lua stack after lua_call     _clr_r8(p);         \/\/some functions have 3rd argument, lua_tostring == lua_tolstring(L, idx, 0);     _call(p, lua_to(argt[0]));      if (argt[0] == 'f' || argt[0] == 'd') _st_xmm0(p, 32); else _st_rax(p, 32); \/\/store return value on stack to call lua_pop(L, 1)      _mov_rcx_rbx(p);     _mov_rdx_DW(p, -2);     _call(p, lua_settop); \/\/lua_pop(L, 1) == lua_settop(L, -2);      if (argt[0] == 'f' || argt[0] == 'd') _ld_xmm0(p, 32); else _ld_rax(p, 32); \/\/return value in rax\/xmm0      _add_rsp_DW(p, 48);    \/\/restore stack     _pop_rbx(p);        \/\/and rbx     _ret(p);   }   return p - code; }<\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  <\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>  \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0430\u0441\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0431\u0435\u0437 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0435\u0441\u043b\u0438 \u0438 \u043d\u0435 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043e\u0431\u0451\u0440\u0442\u043e\u043a \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0432 Lua, \u0442\u043e \u0445\u043e\u0442\u044f \u0431\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043d\u0430 Lua.<\/p>\n<p>  <a href=\"https:\/\/github.com\/pavel212\/uffi\" rel=\"nofollow noopener noreferrer\">github.com\/pavel212\/uffi<\/a><\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/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\/articles\/746658\/\"> https:\/\/habr.com\/ru\/articles\/746658\/<\/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\">\u041f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u043e\u0433\u043e <abbr title=\"Foreign Function Interface\">FFI<\/abbr> \u0434\u043b\u044f Lua \u043f\u043e\u0434 x64 windows, \u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u0435\u0449\u0451 \u0438 linux (\u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e, SysV ABI). <\/p>\n<p>  \u041d\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u0442\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c:<\/p>\n<pre><code class=\"lua\">local ffi = require (\"ffi\") local msg = ffi(\"user32.dll\", \"MessageBoxA\") msg(0, \"Message\", \"Title\", 0)<\/code><\/pre>\n<p>  \u0438\u043b\u0438 \u0432\u0437\u044f\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 glfw3.dll, \u0438 \u043f\u0443\u0442\u0451\u043c<\/p>\n<pre><code class=\"lua\">local glfw = ffi(\"glfw3\")<\/code><\/pre>\n<p>  \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0441\u0435 \u044d\u043ac\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 glfw3.dll \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c\u0438 \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u0438\u0437 Lua.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/pa\/m4\/0x\/pam40xaogfwbdladb_-d6fv5nuy.png\" align=\"right\" data-src=\"https:\/\/habrastorage.org\/webt\/pa\/m4\/0x\/pam40xaogfwbdladb_-d6fv5nuy.png\"\/>\u0420\u0430\u0437\u043c\u0435\u0440 \u0441\u0430\u043c\u043e\u0439 ffi.dll \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f \u0430\u0436 9 \u041a\u0431\u0430\u0439\u0442, \u0432\u043e\u0442 \u043e\u043d\u0430 \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u043d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c 32\u044596 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439. \u041c\u043e\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u044d\u0442\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u0441\u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 bmp (\u0445\u0430\u0431\u0440 \u043d\u0435 \u0443\u043c\u0435\u0435\u0442 \u0432 bmp, \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c \u0432 png), \u043f\u043e\u0442\u043e\u043c \u0440\u0443\u043a\u0430\u043c\u0438 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0435 54 \u0431\u0430\u0439\u0442\u0430 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 (\u0434\u043e &#8216;MZ&#8217;) \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f.<\/p>\n<p>  \u041d\u043e \u043e\u0447\u0435\u043d\u044c \u043e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u0432 \u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u0443\u044e \u0434\u0435\u0442\u0441\u043a\u0443\u044e \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0443 Lua \u0437\u0430\u043b\u0435\u0437\u043b\u0438 \u0433\u0440\u044f\u0437\u043d\u044b\u043c\u0438 \u0441\u0430\u043f\u043e\u0433\u0430\u043c\u0438, \u043f\u0440\u0438\u0442\u0430\u0449\u0438\u043b\u0438 \u0442\u0443\u0434\u0430 \u0432\u0441\u044f\u043a\u0438\u0435 \u043d\u0435\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0435 \u0448\u0442\u0443\u043a\u0438 \u0438\u0437 \u0421, \u0432\u0440\u043e\u0434\u0435 \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u044c\u044e \u0438 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u0441 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f\u043c\u0438 \u0432\u0438\u0434\u0430 *(double*) (void * ptr), \u0438 \u0432\u043e\u043e\u0431\u0449\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0430\u043a\u0438\u0445 \u0432\u0435\u0449\u0435\u0439 \u0443\u0447\u0438\u0442 \u0432\u0441\u044f\u043a\u043e\u043c\u0443 \u043d\u0435\u0445\u043e\u0440\u043e\u0448\u0435\u043c\u0443. <\/p>\n<p>  \u0422\u0443\u0442 \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u0432\u044b\u0445\u043e\u0434\u0438\u043b \u0440\u044f\u0434 \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u0440\u043e \u00ab\u0432\u0440\u0435\u0434\u043d\u044b\u0435 \u0441\u043e\u0432\u0435\u0442\u044b\u00bb \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u00ab60 \u0430\u043d\u0442\u0438\u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u0432 \u0434\u043b\u044f \u0421++ \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0430\u00bb. \u041f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0432\u043e\u043f\u043b\u043e\u0449\u0435\u043d\u0438\u0435 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u0438\u0437 \u043d\u0438\u0445, \u043d\u0435 \u0432\u0441\u0435\u0445 \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043d\u0435 \u0432\u0441\u0435 \u0438\u0437 \u043d\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c\u044b \u043a \u0421, \u0431\u0435\u0437 \u043f\u043b\u044e\u0441\u043e\u0432 \ud83d\ude42  <\/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-398204","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/398204","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=398204"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/398204\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=398204"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=398204"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=398204"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}