PHP 7.4 рдореЗрдВ, FFI рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛, рдЕрд░реНрдерд╛рдд рдЖрдк рд╕реА рдореЗрдВ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЛ рдХрдиреЗрдХреНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рдпрд╛, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд░рд╕реНрдЯ) рд╕реАрдзреЗ, рдПрдХ рдкреВрд░реЗ рд╡рд┐рд╕реНрддрд╛рд░ рдХреЛ рд▓рд┐рдЦрдиреЗ рдФрд░ рдЗрд╕рдХреА рдХрдИ рдмрд╛рд░реАрдХрд┐рдпреЛрдВ рдХреЛ рд╕рдордЭрдиреЗ рдХреЗ рдмрд┐рдирд╛ред
рдЖрдЗрдП Rust рдореЗрдВ рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ, рдФрд░ рдЗрд╕реЗ PHP рдкреНрд░реЛрдЧреНрд░рд╛рдо рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
PHP 7.4 рдореЗрдВ FFI рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рд╡рд┐рдЪрд╛рд░ LuaJIT рдФрд░ рдкрд╛рдпрдерди рд╕реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЕрд░реНрдерд╛рддреН: рдПрдХ рдкрд╛рд░реНрд╕рд░ рднрд╛рд╖рд╛ рдореЗрдВ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдЬреЛ рдХрд╛рд░реНрдпреЛрдВ, рд╕рдВрд░рдЪрдирд╛рдУрдВ рдЖрджрд┐ рдХреА рдШреЛрд╖рдгрд╛рдУрдВ рдХреЛ рд╕рдордЭрддрд╛ рд╣реИред рд╕реА рднрд╛рд╖рд╛ред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдЖрдк рд╣реЗрдбрд░ рдлрд╝рд╛рдЗрд▓ рдХреА рд╕рдВрдкреВрд░реНрдг рд╕рд╛рдордЧреНрд░реА рдХреЛ рд╡рд╣рд╛рдВ рдЦрд┐рд╕рдХрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рддреБрд░рдВрдд рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╢реБрд░реВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдПрдХ рдЙрджрд╛рд╣рд░рдг:
<?php
рдХрд┐рд╕реА рдХреЗ рддреИрдпрд╛рд░ рдХрд┐рдП рдЧрдП рд▓реЛрдЧреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рд╕рд░рд▓ рдФрд░ рдордЬреЗрджрд╛рд░ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдк рдЦреБрдж рднреА рдХреБрдЫ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдПрдХ рдлрд╝рд╛рдЗрд▓ рдХреЛ рдЬрд▓реНрджреА рд╕реЗ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рдкреАрдПрдЪрдкреА рд╕реЗ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
рддреАрди рдкреНрд░рдгрд╛рд▓реА рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рд╕реЗ (C, C ++, Rust), рдореИрдВ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рдмрд╛рдж рдХрд╛ рдЪрдпрди рдХрд░рддрд╛ рд╣реВрдВред рдХрд╛рд░рдг рд╕рд░рд▓ рд╣реИ: рдореЗрд░реЗ рдкрд╛рд╕ C рдпрд╛ C ++ рдореЗрдВ рдореЗрдореЛрд░реА-рд╕реБрд░рдХреНрд╖рд┐рдд рдкреНрд░реЛрдЧреНрд░рд╛рдо рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдпреЛрдЧреНрдпрддрд╛ рдирд╣реАрдВ рд╣реИред рдЬрдВрдЧ рдЬрдЯрд┐рд▓ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕ рдЕрд░реНрде рдореЗрдВ рдпрд╣ рдЕрдзрд┐рдХ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рджрд┐рдЦрддрд╛ рд╣реИред рдХрдВрдкрд╛рдЗрд▓рд░ рддреБрд░рдВрдд рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдХрд╣рд╛рдВ рдЧрд▓рдд рд╣реИрдВред рдЕрдирд┐рд░реНрдзрд╛рд░рд┐рдд рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд▓рдЧрднрдЧ рдЕрд╕рдВрднрд╡ рд╣реИред
рдЕрд╕реНрд╡реАрдХрд░рдг: рдореИрдВ рдПрдХ рд╕рд┐рд╕реНрдЯрдо рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдирд╣реАрдВ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рдЕрдкрдиреЗ рдЬреЛрдЦрд┐рдо рдкрд░ рдмрд╛рдХреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
рдЖрдЗрдП рдХреБрдЫ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рд░рд▓, рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рдХрд╛рд░реНрдп рд▓рд┐рдЦрдХрд░ рд╢реБрд░реВ рдХрд░реЗрдВред рдмрд╕ рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдХреЗ рд▓рд┐рдПред рдФрд░ рдлрд┐рд░ рдЪрд▓рд┐рдП рдПрдХ рдФрд░ рдореБрд╢реНрдХрд┐рд▓ рдХрд╛рдо рдкрд░ рдЪрд▓рддреЗ рд╣реИрдВред
рдПрдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдмрдирд╛рдПрдБ
cargo new hellofromrust --lib
рдФрд░ рдХрд╛рд░реНрдЧреЛ рдореЗрдВ рдЗрдВрдЧрд┐рдд рдХрд░реЗрдВред рдпрд╣ рдмрддрд╛рдПрдВ рдХрд┐ рдпрд╣ рдПрдХ рдЧрддрд┐рд╢реАрд▓ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╣реИ (dylib)
тАж. [lib] name="hellofromrust" crate-type = ["dylib"] тАж.
рд░рд╛рд╕реНрдЯ рдкрд░ рд╣реА рдлрд╝рдВрдХреНрд╢рди рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ
#[no_mangle] pub extern "C" fn addNumbers(x: i32, y: i32) -> i32 { x + y }
рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдпрд╛рдиреА рд╕рд╛рдорд╛рдиреНрдп рдХрд╛рд░реНрдп, рдХреЗрд╡рд▓ рдХреБрдЫ рдЬрд╛рджреБрдИ рд╢рдмреНрдж no_mangle рдФрд░ рдмрд╛рд╣рд░реА "C" рдЬреЛрдбрд╝реЗ рдЬрд╛рддреЗ рд╣реИрдВ
рдЕрдЧрд▓рд╛, рд╣рдо рдХрд╛рд░реНрдЧреЛ рдлрд╛рдЗрд▓ рдХреЛ рд▓рд┐рдирдХреНрд╕ (рд▓рд┐рдирдХреНрд╕ рдХреЗ рддрд╣рдд) рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░рддреЗ рд╣реИрдВ
Php рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
<?php $ffi = FFI::cdef("int addNumbers(int x, int y);", './libhellofromrust.so'); print "1+2=" . $ffi->addNumbers(1, 2) . "\n";
рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рдЖрд╕рд╛рди рд╣реИред рдлрд╝рдВрдХреНрд╢рди рдорд╛рди рджреНрд╡рд╛рд░рд╛ рдкреВрд░реНрдгрд╛рдВрдХ рддрд░реНрдХ рд▓реЗрддрд╛ рд╣реИ, рдФрд░ рдПрдХ рдирдпрд╛ рдкреВрд░реНрдгрд╛рдВрдХ рджреЗрддрд╛ рд╣реИред
рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рдЖрдкрдХреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ? рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рдХреЛрдИ рдлрд╝рдВрдХреНрд╢рди рддрддреНрд╡реЛрдВ рдХреЗ рдкреЗрдбрд╝ рдХреЗ рд▓рд┐рдП рдПрдХ рд▓рд┐рдВрдХ рджреЗрддрд╛ рд╣реИ? рдФрд░ рдлрд╝рдВрдХреНрд╢рди рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдореЗрдВ рд░реИрд╕реНрдЯ рдХреЗ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдирд┐рд░реНрдорд╛рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реЗрдВ?
рдЗрди рд╕рд╡рд╛рд▓реЛрдВ рдиреЗ рдореБрдЭреЗ рдкреНрд░рддрд╛рдбрд╝рд┐рдд рдХрд┐рдпрд╛, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рд░реИрд╕реНрдЯ рдкрд░ рдЕрдВрдХрдЧрдгрд┐рдд рдХреЗ рднрд╛рд╡реЛрдВ рдХрд╛ рдПрдХ рдкреИрд░рд╛рдЧреНрд░рд╛рдл рд▓рд┐рдЦрд╛ред рдФрд░ рдореИрдВрдиреЗ рдЗрд╕реЗ рд╕рднреА рдмрд╛рд░реАрдХрд┐рдпреЛрдВ рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП PHP рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред
рдкреВрд░реНрдг рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛрдб рдпрд╣рд╛рдВ рд╣реИ: рд╕рд░рд▓-рдЬрдВрдЧ-рдЕрдВрдХрдЧрдгрд┐рдд-рдкрд╛рд░реНрд╕рд░ ред рд╡реИрд╕реЗ, рдореИрдВрдиреЗ рдЗрд╕рдореЗрдВ рдПрдХ рдбреЙрдХрдЯрд░ рдЫрд╡рд┐ рднреА рд░рдЦреА рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдкреАрдПрдЪрдкреА (рдПрдлрдПрдлрдЖрдИ рдХреЗ рд╕рд╛рде рд╕рдВрдХрд▓рд┐рдд), рд░рд╕реНрдЯ, рд╕реАрдмрдЧреЗрди, рдЖрджрд┐ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рдЖрдкрдХреЛ рдЬреЛ рдХреБрдЫ рднреА рдЪрд▓рд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдкрд╛рд░реНрд╕рд░, рдпрджрд┐ рд╣рдо рд╢реБрджреНрдз рд░рд╛рд╕реНрдЯ рднрд╛рд╖рд╛ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдирд┐рдореНрди рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ:
" 100500*(2+35)-2*5
" рдлреЙрд░реНрдо рдХреА рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд▓реЗрддрд╛ рд╣реИ рдФрд░ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЛ рдЬреЛрдбрд╝рддрд╛ рд╣реИред рдЯреНрд░реА рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдореЗрдВ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ:
pub enum Expression { Add(Box<Expression>, Box<Expression>), Subtract(Box<Expression>, Box<Expression>), Multiply(Box<Expression>, Box<Expression>), Divide(Box<Expression>, Box<Expression>), UnaryMinus(Box<Expression>), Value(i64), }
рдпрд╣ рдПрдХ рд░рд╛рд╕реНрдЯ рдПрдирдо рд╣реИ, рдФрд░ рд░реИрд╕реНрдЯ рдореЗрдВ, рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ, рдПрдирдо рдХреЗрд╡рд▓ рд╕реНрдерд┐рд░рд╛рдВрдХ рдХрд╛ рдПрдХ рд╕реЗрдЯ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдк рдЕрднреА рднреА рдЙрдирдХреЗ рд▓рд┐рдП рдПрдХ рдореВрд▓реНрдп рдмрд╛рдБрдз рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣рд╛рдВ, рдпрджрд┐ рдиреЛрдб рдкреНрд░рдХрд╛рд░ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ :: рдорд╛рди рд╣реИ, рддреЛ рдПрдХ рдкреВрд░реНрдгрд╛рдВрдХ рдЗрд╕рдХреЗ рд▓рд┐рдП рд▓рд┐рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, 100500ред рдкреНрд░рдХрд╛рд░ рдХреЗ рдиреЛрдб рдХреЗ рд▓рд┐рдП, рд╣рдо рдЗрд╕ рд▓рд┐рдВрдХ рдХреЗ рдСрдкрд░реЗрдВрдб рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рдХреЗ рд▓рд┐рдП рджреЛ рд▓рд┐рдВрдХ (рдмреЙрдХреНрд╕) рднреА рд╕реНрдЯреЛрд░ рдХрд░реЗрдВрдЧреЗред
рдореИрдВрдиреЗ рд░рд╕реНрдЯрд░ рдХреЗ рд╕реАрдорд┐рдд рдЬреНрдЮрд╛рди рдХреЗ рдмрд╛рд╡рдЬреВрдж рдмрд╣реБрдд рддреЗрдЬреА рд╕реЗ рдкрд╛рд░реНрд╕рд░ рдХреЛ рд▓рд┐рдЦрд╛, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдПрдлрдПрдлрдЖрдИ рдХреЗ рд╕рд╛рде рдЦреБрдж рдХреЛ рдкреАрдбрд╝рд╛ рджреЗрдирд╛ рдкрдбрд╝рд╛ред рдпрджрд┐ C рдореЗрдВ рддрд╛рд░ рдПрдХ рдЪрд╛рд░ * рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╕реВрдЪрдХ рд╣реИ, рдЕрд░реНрдерд╛рддред рд╡рд░реНрдгреЛрдВ рдХреЗ рдПрдХ рд╕рд░рдгреА рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реВрдЪрдХ \ 0 рдореЗрдВ рд╕рдорд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рдлрд┐рд░ рд░рд╛рд╕реНрдЯ рдореЗрдВ рдпрд╣ рдПрдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рдкреНрд░рдХрд╛рд░ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдЖрдкрдХреЛ рдЗрдирдкреБрдЯ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдирд┐рдореНрди рдкреНрд░рдХрд╛рд░ рд╕реЗ & str рдкреНрд░рдХрд╛рд░ рдореЗрдВ рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛:
CStr::from_ptr(s).to_str()
CStr рдкрд░ рдЕрдзрд┐рдХ
рдпрд╣ рд╕рдм рдЖрдзреА рдкрд░реЗрд╢рд╛рдиреА рд╣реИред рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ C рдореЗрдВ рдХреЛрдИ Rast Enums рдпрд╛ рд╕реБрд░рдХреНрд╖рд┐рдд рдмреЙрдХреНрд╕ рд▓рд┐рдВрдХ рдирд╣реАрдВ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рдореБрдЭреЗ рд╕реА-рд╕реНрдЯрд╛рдЗрд▓ рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рдЯреНрд░реА, рдпрд╛рдиреА, рдХреЗ рднрдВрдбрд╛рд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рдлрд╝рд┐рдлреА рд╕рдВрд░рдЪрдирд╛ рддреИрдпрд╛рд░ рдХрд░рдиреА рдереАред рд╕рдВрд░рдЪрдирд╛, рд╕рдВрдШ рдФрд░ рд╕рд░рд▓ рд╕рдВрдХреЗрдд ( ffi.rs ) рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗред
#[repr(C)] pub struct ExpressionFfi { expression_type: ExpressionType, data: ExpressionData, } #[repr(u8)] pub enum ExpressionType { Add = 0, Subtract = 1, Multiply = 2, Divide = 3, UnaryMinus = 4, Value = 5, } #[repr(C)] pub union ExpressionData { pair_operands: PairOperands, single_operand: *mut ExpressionFfi, value: i64, } #[derive(Copy, Clone)] #[repr(C)] pub struct PairOperands { left: *mut ExpressionFfi, right: *mut ExpressionFfi, }
рдЦреИрд░, рдФрд░ рдЗрд╕реЗ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рдзрд┐:
impl Expression { fn convert_to_c(&self) -> *mut ExpressionFfi { let expression_data = match self { Value(value) => ExpressionData { value: *value }, Add(left, right) | Subtract(left, right) | Multiply(left, right) | Divide(left, right) => ExpressionData { pair_operands: PairOperands { left: left.convert_to_c(), right: right.convert_to_c(), }, }, UnaryMinus(operand) => ExpressionData { single_operand: operand.convert_to_c(), }, }; let expression_ffi = match self { Add(_, _) => ExpressionFfi { expression_type: ExpressionType::Add, data: expression_data, }, Subtract(_, _) => ExpressionFfi { expression_type: ExpressionType::Subtract, data: expression_data, }, Multiply(_, _) => ExpressionFfi { expression_type: ExpressionType::Multiply, data: expression_data, }, Divide(_, _) => ExpressionFfi { expression_type: ExpressionType::Multiply, data: expression_data, }, UnaryMinus(_) => ExpressionFfi { expression_type: ExpressionType::UnaryMinus, data: expression_data, }, Value(_) => ExpressionFfi { expression_type: ExpressionType::Value, data: expression_data, }, }; Box::into_raw(Box::new(expression_ffi)) } }
Box::into_raw
Box
рдХреЛ рдХрдЪреНрдЪреЗ рд╕реВрдЪрдХ рдореЗрдВ рдмрджрд▓ рджреЗрддрд╛ рд╣реИ
рдирддреАрдЬрддрди, рдлрд╝рдВрдХреНрд╢рди рдЬрд┐рд╕реЗ рд╣рдо PHP рдореЗрдВ рдирд┐рд░реНрдпрд╛рдд рдХрд░реЗрдВрдЧреЗ рд╡рд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
#[no_mangle] pub extern "C" fn parse_arithmetic(s: *const c_char) -> *mut ExpressionFfi { unsafe {
рдпрд╣рд╛рдВ рдЕрдирдкреНрд░реИрдк () рдХрд╛ рдПрдХ рдЧреБрдЪреНрдЫрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ "рдХрд┐рд╕реА рднреА рддреНрд░реБрдЯрд┐ рдХреЗ рд▓рд┐рдП рдШрдмрд░рд╛рд╣рдЯред" рд╕рд╛рдорд╛рдиреНрдп рдЙрддреНрдкрд╛рджрди рдХреЛрдб рдореЗрдВ, рдмреЗрд╢рдХ, рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рд╕реА рдлрд╝рдВрдХреНрд╢рди рдХреА рд╡рд╛рдкрд╕реА рдХреЗ рд╣рд┐рд╕реНрд╕реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рддреНрд░реБрдЯрд┐ рдкрд╛рд░рд┐рдд рдХреА рдЧрдИред
рдЦреИрд░, рдпрд╣рд╛рдВ рд╣рдо рдПрдХ рдордЬрдмреВрд░ рдЕрд╕реБрд░рдХреНрд╖рд┐рдд рдмреНрд▓реЙрдХ рджреЗрдЦрддреЗ рд╣реИрдВ, рдЗрд╕рдХреЗ рдмрд┐рдирд╛, рдХреБрдЫ рднреА рд╕рдВрдХрд▓рд┐рдд рдирд╣реАрдВ рд╣реЛрддрд╛ред рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд░рдо рдореЗрдВ, рдореЗрдореЛрд░реА рд╕реБрд░рдХреНрд╖рд╛ рдХреЗ рд▓рд┐рдП рд░рд╕реНрдЯ рдХрдВрдкрд╛рдЗрд▓рд░ рдЬрд┐рдореНрдореЗрджрд╛рд░ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рд╕рдордЭрдиреЗ рдпреЛрдЧреНрдп рдФрд░ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд╣реИред рдЬрдВрдЧ рдФрд░ рд╕реА рдХреЗ рдЬрдВрдХреНрд╢рди рдкрд░, рдпрд╣ рд╣рдореЗрд╢рд╛ рд░рд╣реЗрдЧрд╛ред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЕрдиреНрдп рд╕рднреА рд╕реНрдерд╛рдиреЛрдВ рдореЗрдВ рд╕рдм рдХреБрдЫ рдмрд┐рд▓реНрдХреБрд▓ рдирд┐рдпрдВрддреНрд░рд┐рдд рдФрд░ рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИред
рдлреБрдл, рдпрд╣ рд╕рдм рдХреБрдЫ рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рдФрд░ рдЕрддрд┐ рд╕реВрдХреНрд╖реНрдо рдЕрдВрддрд░ рд╣реИ: рдЖрдкрдХреЛ рдЕрднреА рднреА рд╣реЗрдбрд░ рдирд┐рд░реНрдорд╛рдг рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рддрд╛рдХрд┐ PHP рдлрд╝рдВрдХреНрд╢рди рдФрд░ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХреЛ рд╕рдордЭ рд╕рдХреЗред
рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рд░рд╛рд╕реНрдЯ рдореЗрдВ рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╕рд┐рдмрд┐рдВрдбрдЧреЗрди рдЙрдкрдХрд░рдг рд╣реИред рдпрд╣ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдирд┐рд░реНрдорд╛рдгреЛрдВ рдХреЗ рд▓рд┐рдП рд░рд╛рд╕реНрдЯ рдХреЛрдб рдореЗрдВ рдЦреЛрдЬ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рдиреНрд╣реЗрдВ рдмрд╛рд╣рд░реА "рд╕реА", рд░рд┐рдкреНрд░ (рд╕реА), рдЖрджрд┐ рд▓реЗрдмрд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдФрд░ рд╣реЗрдбрд░ рдлрд╛рдЗрд▓ рдЬрдирд░реЗрдЯ рдХрд░реЗрдВ
рдореБрдЭреЗ cbindgen рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЗ рд╕рд╛рде рдереЛрдбрд╝рд╛ рдиреБрдХрд╕рд╛рди рдЙрдард╛рдирд╛ рдкрдбрд╝рд╛, рд╡реЗ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдирд┐рдХрд▓реЗ ( cbindgen.toml ):
language = "C" no_includes = true style="tag" [parse] parse_deps = true
рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдореИрдВ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╕рднреА рдмрд╛рд░реАрдХрд┐рдпреЛрдВ рдХреЛ рд╕рдордЭрддрд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ)
рд▓реЙрдиреНрдЪ рдЙрджрд╛рд╣рд░рдг:
cbindgen . -o target/testffi.h
рдкрд░рд┐рдгрд╛рдо рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реЛрдЧрд╛:
enum ExpressionType { Add = 0, Subtract = 1, Multiply = 2, Divide = 3, UnaryMinus = 4, Value = 5, }; typedef uint8_t ExpressionType; struct PairOperands { struct ExpressionFfi *left; struct ExpressionFfi *right; }; union ExpressionData { struct PairOperands pair_operands; struct ExpressionFfi *single_operand; int64_t value; }; struct ExpressionFfi { ExpressionType expression_type; union ExpressionData data; }; struct ExpressionFfi *parse_arithmetic(const char *s);
рддреЛ, рд╣рдордиреЗ рдПрдЪ-рдлрд╛рдЗрд▓ рдЬреЗрдирд░реЗрдЯ рдХрд┐рдпрд╛, cargo build
рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░реЗрдВ рдФрд░ рдЖрдк рд╣рдорд╛рд░реЗ php рдХреЛрдб рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВред рдХреЛрдб рдХреЗрд╡рд▓ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдкреНрд░рд┐рдВрдЯрд╕реНрдЯреЗрдкреЗрд╢рди рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рд╛рде рд╕реНрдХреНрд░реАрди рдкрд░ рд╣рдорд╛рд░реА рд░рд╕реНрдЯ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рджреНрд╡рд╛рд░рд╛ рдкрд╛рд░реНрд╕ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
<?php $cdef = \FFI::cdef(file_get_contents("target/testffi.h"), "target/debug/libexpr_parser.so"); $expression = $cdef->parse_arithmetic("-6-(4+5)+(5+5)*(4-4)"); printExpression($expression); class ExpressionKind { const Add = 0; const Subtract = 1; const Multiply = 2; const Divide = 3; const UnaryMinus = 4; const Value = 5; } function printExpression($expression) { switch ($expression->expression_type) { case ExpressionKind::Add: case ExpressionKind::Subtract: case ExpressionKind::Multiply: case ExpressionKind::Divide: $operations = ["+", "-", "*", "/"]; print "("; printExpression($expression->data->pair_operands->left); print $operations[$expression->expression_type]; printExpression($expression->data->pair_operands->right); print ")"; break; case ExpressionKind::UnaryMinus: print "-"; printExpression($expression->data->single_operand); break; case ExpressionKind::Value: print $expression->data->value; break; } }
рдЦреИрд░, рдпрд╣ рддреЛ рд╣реИ, рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред
рднрд╛рдбрд╝ рдореЗрдВ рдЬрд╛рдУ "рд╕рдм рдХреБрдЫ рдерд╛ред" рд╕реНрдореГрддрд┐ рдХреЛ рдЕрднреА рднреА рд╕рд╛рдлрд╝ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд░реИрд╕реНрдЯ рдЕрдкрдиреЗ рдЬрд╛рджреВ рдХреЛ рд░реИрд╕реНрдЯ рдХреЛрдб рдХреЗ рдмрд╛рд╣рд░ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рд╣реИред
рдПрдХ рдФрд░ рд╡рд┐рдирд╛рд╢ рдлрд╝рдВрдХреНрд╢рди рдЬреЛрдбрд╝реЗрдВ
#[no_mangle] pub extern "C" fn destroy(expression: *mut ExpressionFfi) { unsafe { match (*expression).expression_type { ExpressionType::Add | ExpressionType::Subtract | ExpressionType::Multiply | ExpressionType::Divide => { destroy((*expression).data.pair_operands.right); destroy((*expression).data.pair_operands.left); Box::from_raw(expression); } ExpressionType::UnaryMinus => { destroy((*expression).data.single_operand); Box::from_raw(expression); } ExpressionType::Value => { Box::from_raw(expression); } }; } }
Box::from_raw(expression);
- рдХрдЪреНрдЪреЗ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рдмреЙрдХреНрд╕ рдкреНрд░рдХрд╛рд░ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЪреВрдВрдХрд┐ рдЗрд╕ рд░реВрдкрд╛рдВрддрд░рдг рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдХрд┐рд╕реА рдХреЗ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрдм рдЖрдк рджрд╛рдпрд░реЗ рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рддреЗ рд╣реИрдВ рддреЛ рдореЗрдореЛрд░реА рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдирд╖реНрдЯ рд╣реЛ рдЬрд╛рддреА рд╣реИред
рд╣реЗрдбрд░ рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдиреЗ рдФрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдордд рднреВрд▓рдирд╛ред
рдФрд░ php рдореЗрдВ рд╣рдо рдЕрдкрдиреЗ рдлрдВрдХреНрд╢рди рдореЗрдВ рдХреЙрд▓ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ
$cdef->destroy($expression);
рдЕрдм рдмрд╕ рдЗрддрдирд╛ рд╣реАред рдпрджрд┐ рдЖрдк рдЬреЛрдбрд╝рдирд╛ рдпрд╛ рдмрддрд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рдореИрдВ рдХрд╣реАрдВ рдЧрд▓рдд рдерд╛, рддреЛ рдХреГрдкрдпрд╛ рдмреЗрдЭрд┐рдЭрдХ рдЯрд┐рдкреНрдкрдгреА рдХрд░реЗрдВред
рдПрдХ рдкреВрд░реНрдг рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рд╛рде рдПрдХ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рд▓рд┐рдВрдХ рдкрд░ рд╕реНрдерд┐рдд рд╣реИ: [ https://github.com/anton-okolelov/simple-rust-arithmetic-parser ]
рдкреБрдирд╢реНрдЪ рд╣рдо рдЬрд┐рдВрдХ рдЙрддреНрдкрд╛рдж рдкреЙрдбрдХрд╛рд╕реНрдЯ рдХреЗ рдЕрдЧрд▓реЗ рдЕрдВрдХ рдореЗрдВ рдЗрд╕ рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░реЗрдВрдЧреЗ, рдЗрд╕рд▓рд┐рдП рдкреЙрдбрдХрд╛рд╕реНрдЯ рдХреА рд╕рджрд╕реНрдпрддрд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВред