diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/2q b/2q new file mode 100644 index 0000000..f57f6f7 --- /dev/null +++ b/2q @@ -0,0 +1,25 @@ +use std::ffi::CStr; +use std::ffi::c_char; + +#[cfg(target_family = "unix")] +extern "C" { + fn _2_c_func() -> *const c_char; +} + +fn main() -> Result<(), String> { + let raw_string_pointer: *const c_char = unsafe { _2_c_func() }; + if raw_string_pointer.is_null() { + return Err(String::from("pointer is null")); + }; + let c_string = unsafe { CStr::from_ptr(raw_string_pointer) }; // SAFETY: we are assuming the + // string is null terminated since we created it ourselves in a previous program. However, if + // it is not, it is UB. + + let Some(string) = c_string.to_str() else { + return Err(String::from("string should be null terminated")) + }; + + println!("{}", string); + Ok(()) +} + diff --git a/Makefile b/Makefile index 34d905b..a9d9314 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ # -L target -l 2_c 2_c: 1_assembly - gcc -Wall -Wpedantic -Werror src/2_c.c -c -o target/2_c.o + gcc -Wall -Wpedantic -Werror src/2_c.c -c -fPIC -o target/2_c.o # ar rcs target/lib2_c.a target/2_c.o 1_assembly: diff --git a/README.md b/README.md new file mode 100644 index 0000000..9c384fd --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# Chinese Whispers +A project to pass a string between as many languages as I know. diff --git a/src/1_assembly.S b/src/1_assembly.S index c5520b7..24c239a 100644 --- a/src/1_assembly.S +++ b/src/1_assembly.S @@ -10,9 +10,9 @@ section .text ; syscall ; invoke operating system to exit _1_assembly_func: - mov rax, message + lea rax, [rel message] ret section .data -message: db "Hello from Assembly.", 21 ; note the newline at the end; Define variables in the data section +message: db "Hello from Assembly.", 0xA, 23 ; note the newline at the end; Define variables in the data section diff --git a/src/2_c.c b/src/2_c.c index df0392d..3ff4e40 100644 --- a/src/2_c.c +++ b/src/2_c.c @@ -5,10 +5,9 @@ extern char* _1_assembly_func(void); char* _2_c_func() { char * asm_buf = _1_assembly_func(); - char * buf = malloc(22 + 16); - memcpy(buf, asm_buf, 22); - strcat(buf, "\nHello from C."); + char * buf = malloc(24 + 16); + memcpy(buf, asm_buf, 24); + strcat(buf, "Hello from C.\n"); - printf("%s", buf); return buf; } diff --git a/src/3_rust.rs b/src/3_rust.rs new file mode 100644 index 0000000..2bca2e7 --- /dev/null +++ b/src/3_rust.rs @@ -0,0 +1,27 @@ +use std::ffi::CStr; +use std::ffi::c_char; + +#[cfg(target_family = "unix")] +extern "C" { + fn _2_c_func() -> *const c_char; +} + +fn main() -> Result<(), String> { + let raw_string_pointer: *const c_char = unsafe { _2_c_func() }; + if raw_string_pointer.is_null() { + return Err(String::from("pointer is null")); + }; + let c_string = unsafe { CStr::from_ptr(raw_string_pointer) }; // SAFETY: we are assuming the + // string is null terminated since we created it ourselves in a previous program. However, if + // it is not, it is UB. + + let Ok(string) = c_string.to_str() else { + return Err(String::from("string should be null terminated")) + }; + + let mut string = String::from(string); + string.push_str("Hello from Rust."); + println!("{}", string); + Ok(()) +} +