Rustã®æŠå¿µã«åºæã®çšèªïŒæææš©ãåçšãã©ã€ãã¿ã€ã ãã©ã¡ãŒã¿ãŒïŒã®äžéšã翻蚳ããæ¹æ³ãããããŸããã§ããããã®ããããã·ã¢èªåã®èŠèŽè ã«ãšã£ãŠæå³ãæãããç解ã§ããèšèãéžæããããšããŸããã æ¹åã®ããã®ææ¡ã¯åãå ¥ããããŸãã
1æ©ã§Rustã®äžçæ¯é ãéæããèšç»ã¯ãªãã£ããããRustèªäœã®ãã€ãã£ãã³ãŒããšåããããç°¡åã«æ¢åã®ã³ãŒããšããåãããèœåã匷ãæ±ããããŠããŸãã ããããRustããªãŒããŒããããªãã§C APIãéåžžã«ç°¡åã«äœ¿çšã§ããããã«ããåæã«ãã€ã³ã¿ãŒã®æææš©ãšåçšç®¡çã·ã¹ãã ã®ãããã§ãã¡ã¢ãªç®¡çã®å³æ Œãªã»ãã¥ãªãã£ãä¿èšŒããçç±ã§ãã
ä»ã®èšèªãšã®çžäºäœçšã®ããã«ãRustã¯FFIïŒå€éšé¢æ°ã€ã³ã¿ãŒãã§ãŒã¹-å€éšé¢æ°ãåŒã³åºãããã®ã€ã³ã¿ãŒãã§ãŒã¹ïŒãæäŸããŸãã Rustã®åºæ¬ååã«åŸã£ãŠãFFIã¯ãŒãã³ã¹ãã®æœè±¡åãæäŸãããããRustãšCã®éã§é¢æ°ãåŒã³åºãã³ã¹ãã¯ãCã³ãŒãããCé¢æ°ãåŒã³åºãã³ã¹ããšåãã«ãªããŸãããã€ã³ã¿ãŒããã®ä»ã®ãªãœãŒã¹ã管çããããã®å®å šãªãããã³ã«ãäœæããããã«åçšããŠããŸãã éåžžããã®ãããªãããã³ã«ã¯C APIã®ããã¥ã¡ã³ãã®åœ¢åŒã§ã®ã¿ååšããŸãïŒããã¯æé«ã®ç¶æ ã§ãïŒããRustã¯ãããã®èŠä»¶ãæ瀺ããŸãïŒãããŠããã®å®è£ ã¯ã³ã³ãã€ã©ãŒã«ãã£ãŠä¿èšŒãããŸã-ãããTranslïŒã
ãã®æçš¿ã§ã¯ãCé¢æ°ãåŒã³åºãããã®å®å šã§ãªãã€ã³ã¿ãŒãã§ãŒã¹ãå®å šãªæœè±¡åã«ã«ãã»ã«åããæ¹æ³ãèŠãŠãããŸãã
äž»ãªäŒè©±ã¯Cãšã®å¯Ÿè©±ã«é¢ãããã®ã§ãããRustãä»ã®èšèªïŒRubyãPythonãªã©ïŒãšçµ±åããã®ãåããããç°¡åã§ãã
Rustã¯Cã§åäœããŸã
ç°¡åãªäŸããå§ããŸããããRustããCã³ãŒããåŒã³åºããRustãè¿œå ã³ã¹ãã課ããªãããšã瀺ããŸãã å ¥åã®ä»»æã®æ°ã2åã«ããåçŽãªCããã°ã©ã ã次ã«ç€ºããŸãã
int double_input(int input) { return input * 2; }
Rustãããã®é¢æ°ãåŒã³åºãã«ã¯ã次ã®ã³ãŒããèšè¿°ã§ããŸãã
extern crate libc; extern { fn double_input(input: libc::c_int) -> libc::c_int; } fn main() { let input = 4; let output = unsafe { double_input(input) }; println!("{} * 2 = {}", input, output); }
ããã ãã§ãïŒ GitHubã®ã³ãŒãã䜿çšããŠãã®äŸãè©Šãããšãã§ããŸã-ãã§ãã¯ã¢ãŠãããŠããããžã§ã¯ããã£ã¬ã¯ããªãã
cargo run
ãå®è¡ããã ãã§ãã ã³ãŒããããCé¢æ°ãåŒã³åºãã®ã«è¿œå ã®ãžã§ã¹ãã£ãŒã¯å¿ èŠãªãããã®çœ²åãèšè¿°ããã ãã§ããããšãããããŸãã ããã«ãçæããããã·ã³ã³ãŒãã«ãè¿œå ã³ã¹ããå«ãŸããªãããšãããããŸãã ãã ãããã®Rustããã°ã©ã ã«ã¯ããã€ãã®å°ããªïŒãããæœè¡æ§-ãããTranslãïŒè©³çŽ°ããããŸãããã®ãããæåã«åéšåããã詳现ã«åæããŸãã
ãŸãã
extern crate libc
ã確èªããŸãã libcã¯ã¬ãŒãã«ã¯ãCã§ã®äœæ¥ã«åœ¹ç«ã€FFIã®å€ãã®typedefãå«ãŸããŠããŸãããRustãšCã®éã®åŒã³åºãå¢çã«ããåãäºãã«äžè²«ããŠããããšãä¿èšŒããŸãã
ã©ãã
extern { fn double_input(input: libc::c_int) -> libc::c_int; }
Rustã§ã¯ãããã¯å€éšé¢æ°å®£èšã§ãã ãã®ã³ãŒãã¯ãCã®ããããŒãã¡ã€ã«ã«é¡äŒŒããŠãããšèããããšãã§ããŸããããã§ãã³ã³ãã€ã©ãŒã¯ãé¢æ°ã®å ¥åãã©ã¡ãŒã¿ãŒãšåºåãã©ã¡ãŒã¿ãŒã«ã€ããŠèª¿ã¹ãŸãã ã芧ã®ãšããããã®ã·ã°ããã£ã¯Cã®é¢æ°ã®å®çŸ©ãšäžèŽããŠããŸãã
次ã«ãã¡ã€ã³ããã°ã©ã ã³ãŒãããããŸãã
fn main() { let input = 4; let output = unsafe { double_input(input) }; println!("{} * 2 = {}", input, output); }
Rustã®FFIã®æãéèŠãªåŽé¢ã®1ã€ã¯ã
unsafe
ãããã¯ã§ãã ã³ã³ãã€ã©ãŒã¯
double_input()
é¢æ°ã®å®è£ ã«ã€ããŠäœãç¥ããªããããæåã¯å€éšé¢æ°ãåŒã³åºããšãã«ã¡ã¢ãªãŒç®¡çã»ãã¥ãªãã£ãŒã䟵害ãããå¯èœæ§ããããšæ³å®ããŠããŸãã
unsafe
ãããã¯ã¯ãããã°ã©ããŒã«ã¡ã¢ãªæäœã®å®å šæ§ã確ä¿ãã責任ãè² ãæ©äŒãäžããŸãïŒãã®ããã«ããŠããã®é¢æ°ãåŒã³åºããŠãã¡ã¢ãªã®æŽåæ§ã«éåããªãããšãçŽæããRustã®åºæ¬çãªä¿èšŒãåŒãç¶ãæºããããããã«ããŸãã ãããã¯å³ããããå¶éã®ããã§ãããRustã¯APIãŠãŒã¶ãŒãå®å šã§ãªããããã¯ãå¿é ããªãããã«ååãªè³éãæäŸããŸãïŒå°ãåŸã§ãã®ç¹ãæããã«ãªããŸãïŒã
RustããCé¢æ°åŒã³åºããè¡ãæ¹æ³ã確èªããã®ã§ãRustããã®åŒã³åºãã«å®éã«è¿œå ã³ã¹ãã課ããã©ãããèŠãŠã¿ãŸãããã ã»ãšãã©ãã¹ãŠã®ããã°ã©ãã³ã°èšèªã¯ããªãããã®æ¹æ³ã§Cã³ãŒããåŒã³åºãããšãã§ããŸãããå€ãã®å Žåãããã«ã¯ãããã°ã©ã ã®å®è¡äžã«å°ãªããšãè¿œå ã®åå€æãããã³å Žåã«ãã£ãŠã¯ããè€éãªæäœã䌎ããŸãã Rustã®å®éã®åäœã確èªããã«ã¯ãRustã³ã³ãã€ã©ãŒã
double_input()
ãã
double_input()
ã³ãŒããåç §ããŠã
double_input()
é¢æ°ãåŒã³åºããŸãã
mov $0x4,%edi callq 3bc30 <double_input>
ãããŠããã ãã§ãïŒ ãããããããããã«ãRustããCé¢æ°ãåŒã³åºãã«ã¯ãåŒã³åºããCããã§ãããã®ããã«ãåŒæ°ãš1ã€ã®åŒã³åºãåœä»€ãé 眮ããã ãã§æžã¿ãŸãã
å®å šãªæœè±¡å
Rustã®æ©èœã®ã»ãšãã©ã¯ãããŒã¿æææš©ã®æŠå¿µã«é¢é£ããŠãããFFIãäŸå€ã§ã¯ãããŸããã Rustã§Cã©ã€ãã©ãªã®ãã€ã³ãã£ã³ã°ãäœæãããšããªãŒããŒãããããŒãã«ãªãã ãã§ãªããCèªäœãããå€ãã®ã¡ã¢ãªã®å®å šæ§ãä¿èšŒã§ããŸãïŒ ãã€ã³ãã£ã³ã°ã§ã¯ãRustã®æææš©ãšåçšååã䜿çšããŠãAPIã䜿çšããŠã«ãŒã«ãå³å¯ã«å¶åŸ¡ã§ããŸããããã¯éåžžãCããããŒãã¡ã€ã«ã§ã®ã¿ã³ã¡ã³ããšããŠèšè¿°ãããŸãã
ããšãã°ãtarã¢ãŒã«ã€ããæäœããããã®ã©ã€ãã©ãªãæ³åããŠãã ããã ãã®ã©ã€ãã©ãªã¯ã次ã®ãããªåã¢ãŒã«ã€ããã¡ã€ã«ã®å 容ãèªã¿åãæ©èœãæäŸããŸãã
// Gets the data for a file in the tarball at the given index, returning NULL if // it does not exist. The `size` pointer is filled in with the size of the file // if successful. const char *tarball_file_data(tarball_t *tarball, unsigned index, size_t *size);
ãã®é¢æ°ã¯ããããã©ã®ããã«äœ¿çšããããã«ã€ããŠæé»ã®ä»®å®ãè¡ããŸããè¿ããã
char*
ãã€ã³ã¿ãŒã¯ãå ¥åãã©ã¡ãŒã¿ãŒ
tarball_t *tarball
ä¹ãåãããšãã§ããŸããã Rustã®ãã®APIãžã®ãã€ã³ãã£ã³ã°ã¯æ¬¡ã®ããã«ãªããŸãã
pub struct Tarball { raw: *mut tarball_t } impl Tarball { pub fn file(&self, index: u32) -> Option<&[u8]> { unsafe { let mut size = 0; let data = tarball_file_data(self.raw, index as libc::c_uint, &mut size); if data.is_null() { None } else { Some(slice::from_raw_parts(data as *const u8, size as usize)) } } } }
ããã§ã
*mut tarball_t
Tarball
æ§é äœã«ãã£ãŠææãããŠããŸã
Tarball
æ§é äœã¯ãã¡ã¢ãªãšãªãœãŒã¹ãã¯ãªã¢ãã圹å²ãæãããŸãããã®ãããtarã¢ãŒã«ã€ãã«å²ãåœãŠãããã¡ã¢ãªã©ã€ãã¿ã€ã ã«ã€ããŠååãªç¥èããããŸãã ããã«ã
file()
ã¡ãœããã¯ã
Tarball
æ§é
Tarball
寿åœïŒargument
&self
ïŒã«å¯¿åœãæé»çã«é¢é£ããåçšã¹ã©ã€ã¹ãè¿ããŸãã ãããã£ãŠãRustã¯ãè¿ãããã¹ã©ã€ã¹ãã¢ãŒã«ã€ãæ§é ãã¡ã¢ãªå ã«ããéã®ã¿äœ¿çšã§ããããšã瀺ãããã³ã°ãªã³ã°ãã€ã³ã¿ãŒïŒCèªäœã§ç°¡åã«èªããããïŒã®ãã°ããªãããšãéçã«ä¿èšŒããŸãã ïŒRustã®åçšã«æ £ããŠããªãå Žåã¯ãæææš©ã«é¢ããYehuda Katzã®æçš¿ãèªãããšããå§ãããŸããïŒ
ããã§ãRustã®ãã€ã³ãã£ã³ã°ã®äž»ãªæ©èœã¯ã»ãã¥ãªãã£ã§ããã€ãŸããRustã®ãã®APIã®ãŠãŒã¶ãŒã¯ã
unsafe
ãããã¯ã䜿çšããŠããããåŒã³åºãããšã¯ã§ããŸããã ããã§ã¯å®è£ èªäœã¯å®å šã§ã¯ãããŸãããïŒFFIã䜿çšããŠããããïŒããã®ã€ã³ã¿ãŒãã§ã€ã¹ã¯åçšãã€ã³ã¿ãŒã®ãããã§ãããã䜿çšããRustã³ãŒãã®ã¡ã¢ãªãæäœããã»ãã¥ãªãã£ãä¿èšŒããŸãã ã€ãŸããRustã³ã³ãã€ã©ãŒã¯ãRustã³ãŒããããã®APIã䜿çšããå Žåãåã«ã»ã°ã¡ã³ããŒã·ã§ã³éåãåŒã³åºãããšãã§ããªãããšãéçã«ä¿èšŒããŸãã ãããŠãå¿ããªãã§ãã ããïŒããã¯ãã¹ãŠãè¿œå ã®ãªãŒããŒãããã³ã¹ããè² æ ããŸããïŒ Rustã®ãã¹ãŠã®Cã¿ã€ãã¯ãè¿œå ã®ã¡ã¢ãªèŠä»¶ãªãã§è¡šç€ºãããŸãã
Rustã³ãã¥ããã£ã¯ã OpenSSL ã libgit2 ã libdispatch ã libcurl ã sdl2 ã Unix API ãããã³libsodiumãªã©ãæ¢åã®Cã©ã€ãã©ãªçšã®é©åãªäžé£ã®å®å šãªãã€ã³ãã£ã³ã°ããã§ã«äœæããŠããŸã ã ãã®crates.ioã®ãªã¹ãã¯éåžžã«æ¥éã«æ¡å€§ããŠããããããæ°ã«å ¥ãã®Cã©ã€ãã©ãªããã§ã«Rustãã€ã³ãã£ã³ã°ãæã£ãŠãããããŸããªãäœæãããå¯èœæ§ããããŸãã
Cã¯Rustã§åäœããŸã
ã¡ã¢ãªã®å®å šãªäœ¿çšã®ä¿èšŒã«ãããããããRustã¯ã¬ããŒãžã³ã¬ã¯ã¿ãŒãŸãã¯ã©ã³ã¿ã€ã ã䜿çšããŸãã; Rustã³ãŒãã¯ç¹å¥ãªæºåãªãã§CããåŒã³åºãããšãã§ããŸãã ã€ãŸããRustããã®CåŒã³åºãã ãã§ãªããCããã®RuståŒã³åºãã«ããªãŒããŒãããã¯ãããŸããïŒ
åã®ãã®ã®å察ãåããŸãã åãšåæ§ã«ããã¹ãŠã®ã³ãŒãã¯GitHubã§å©çšã§ããŸã ã ãŸããRustã³ãŒãïŒ
#[no_mangle] pub extern fn double_input(input: i32) -> i32 { input * 2 }
åãšåãããã«ãè€éãªãã®ã¯ãããŸããããããã€ãã®è€éãªæ©èœãæ€èšãã䟡å€ããããŸãã æåã«ãå±æ§
#[no_mangle]
é¢æ°ãããŒã¯ããŸããã ããã¯ã
double_input
é¢æ°ã®ååãæªããå¿ èŠããªããšããã³ã³ãã€ã©ãŒãžã®ã·ã°ãã«ã§ãã Rustã¯C ++ã§äœ¿çšããããã®ãšåæ§ã®ååè£ é£Ÿã䜿çšããŠãç°ãªãã©ã€ãã©ãªéã§ååã®äžææ§ãä¿èšŒããŸãããã®å±æ§ã«ãããCããåŒã³åºããããšãã«ã³ã³ãã€ã©ãé¢æ°ã«äžããååãæšæž¬ã§ããªããªããŸãïŒè£ 食åã¯æ¬¡ã®ããã«ãªããŸãïŒ
double_input::h485dee7f568bebafeaa
ïŒã
次ã«ãé¢æ°å®çŸ©ããããŸãããããã§æãèå³æ·±ãã®ã¯
extern
ããŒã¯ãŒãã§ãã ããã¯ABIé¢æ°ãæå®ããããã®ç¹å¥ãªåœ¢åŒã§ãCããã®é¢æ°åŒã³åºããšäºææ§ããããŸãã
æåŸã«ã
Cargo.toml
ãèŠããšããã®ã©ã€ãã©ãªã¯éåžžã®Rustã©ã€ãã©ãªïŒrlibïŒãšããŠã§ã¯ãªããRustã§ãstaticlibããšåŒã°ããéçã©ã€ãã©ãªãšããŠæ§ç¯ãããŠããããšãããããŸãã ããã«ãããRustã³ãŒããCããã°ã©ã ã«éçã«ãªã³ã¯ã§ããŸãã
Rustã®ã©ã€ãã©ãªãç解ããã®ã§ãããã䜿çšããCããã°ã©ã ãäœæããŸãã
#include <stdint.h> #include <stdio.h> extern int32_t double_input(int32_t input); int main() { int input = 4; int output = double_input(input); printf("%d * 2 = %d\n", input, output); return 0; }
ããã§ã¯ãRustãšåæ§ã«ãCã§Rustã§èšè¿°ãããå€éšé¢æ°
double_input()
ã宣èšããå¿ èŠãããããšã
double_input()
ãŸãã
ãã®è©³çŽ°ã¯å¥ãšããŠãä»ã®ãã¹ãŠã¯ãã§ã«æ©èœããŠããŸãïŒ GitHubã®ãã£ã¬ã¯ããªãã
make
ãå®è¡
make
ãšããã®äŸã¯ã³ã³ãã€ã«ãããŠ1ã€ã®éçå®è¡å¯èœãã¡ã€ã«ã«ã¢ã»ã³ãã«ãããèµ·åæã«
4 * 2 = 8
ãã³ã³ãœãŒã«ã«åºåãããŸãã
ã¬ããŒãžã³ã¬ã¯ã¿ãšã©ã³ã¿ã€ã ç°å¢ãååšããªããããCãRustã«éåžžã«ç°¡åã«çµ±åã§ããŸãã å€éšCã³ãŒãã¯ãRustã®ç°å¢ãèšå®ããããã®ãžã§ã¹ãã£ãŒãè¡ãã¹ãã§ã¯ãªããããRustã³ãŒããšCã®éã®ç§»è¡ã¯éåžžã«å®äŸ¡ã§ãã
Cã®åŸ
ã芧ã®ããã«ãRustã®FFIã¯ãªãŒããŒããããã»ãšãã©äžããŸãããæææš©ã·ã¹ãã ã«ãããRustã®Cã©ã€ãã©ãªã«ã¡ã¢ãªã»ãŒããªãã€ã³ãã£ã³ã°ãæžã蟌ãããšãã§ããŸãã ãã ããCã䜿çšããŠããªãå Žåã§ãããŸã ã©ãããŒã§ãïŒ åãååã«ããã Python ã Ruby ã JavaScriptãããã³ä»ã®å€ãã®èšèªããRustã³ãŒããåŒã³åºãããšãã§ããŸãã
ãããã®èšèªã§ã®ããã°ã©ãã³ã°ã§ã¯ãéèŠãªã³ã³ããŒãã³ããé«éåããããšãå¿ èŠã«ãªãå ŽåããããŸããããã®åã«Cã«ç§»è¡ããå¿ èŠããããããã«ããããããã®èšèªã®ã¡ã¢ãªç®¡çãé«ã¬ãã«ã®æœè±¡åãããã³äººéå·¥åŠã®å®å šæ§ãæŸæ£ãããŸããã
ãã ããRustãCãšã·ãŒã ã¬ã¹ã«çµ±åããããšããäºå®ã¯ãRustããã®ãããªäœ¿çšã«é©ããŠããããšãæå³ããŸãã ãããã¯ã·ã§ã³ã§Rustã䜿çšããæåã®äŒæ¥ã®1ã€ã§ããSkylight㯠ãRustã«åãæ¿ããã ãã§ããŒã¿åéã«ããããã©ãŒãã³ã¹ãã»ãŒç¬æã«æ¹åããã¡ã¢ãªäœ¿çšéãåæžããããšãã§ããŸããããã¹ãŠã®Rustã³ãŒãã¯Ruby gemãšããŠå ¬éãããŸããã
ããã©ãŒãã³ã¹ãæé©åããããã«ããPythonããã³RubyããCèšèªã«åãæ¿ããããšã¯ãããªãæéããããããã»ã¹ã§ããããšãå€ãããããã°ãéåžžã«å°é£ã«ãªãããã«ããã°ã©ã ã倱æããããšãä¿èšŒããããšã¯å°é£ã§ãã Rustã¯ããªãŒããŒãããããŒãã®FFIãæäŸããã ãã§ãªããå ã®èšèªãšåãã»ãã¥ãªãã£ä¿èšŒãç¶æããããšãå¯èœã«ããŸãã é·æçã«ã¯ãããã«ããããããã®èšèªã®ããã°ã©ããŒã¯ããŒããŠã§ã¢ã«è¿ã¥ããå¿ èŠãªå Žæã§çç£æ§ãåäžãããããã«ã·ã¹ãã ããã°ã©ãã³ã°ãå°ãè¿œå ã§ããããã«ãªããŸãã
FFIã¯Rustã®è²¯éç®±ã«ããå€ãã®ããŒã«ã®1ã€ã«ãããŸããããRustã«åãæ¿ããããã®äž»èŠãªã³ã³ããŒãã³ãã§ãããçŸåšååšããã³ãŒããšã®çµ±åãéåžžã«ç°¡åã§ãã ç§ã¯å人çã«ãRustã®çŸåŸ³ãå¯èœãªéãå€ãã®ãããžã§ã¯ãã«ã©ã®ããã«åãå ¥ããããããèŠãŠãšãŠãããããæããŸãïŒ