Added python
Also updated Makefile for ease of use.
This commit is contained in:
@@ -1,25 +0,0 @@
|
|||||||
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(())
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,14 +1,18 @@
|
|||||||
3_rust: 2_c
|
target/4_python.py: target/3_rust src/4_python.py
|
||||||
rustc -Clink-arg=target/1_assembly.o -Clink-arg=target/2_c.o src/3_rust.rs -o target/3_rust --verbose
|
cp src/4_python.py target/4_python.py
|
||||||
# rustc src/3_rust.rs -o target/3_rust --verbose
|
|
||||||
# -L target -l 2_c
|
|
||||||
|
|
||||||
2_c: 1_assembly
|
target/3_rust: target/2_c.o src/3_rust.rs
|
||||||
|
rustc -Clink-arg=target/1_assembly.o -Clink-arg=target/2_c.o src/3_rust.rs -o target/3_rust
|
||||||
|
|
||||||
|
target/2_c.o: target/1_assembly.o src/2_c.c
|
||||||
gcc -Wall -Wpedantic -Werror src/2_c.c -c -fPIC -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:
|
target/1_assembly.o: src/1_assembly.S
|
||||||
nasm -f elf64 src/1_assembly.S -o target/1_assembly.o
|
nasm -f elf64 src/1_assembly.S -o target/1_assembly.o
|
||||||
|
|
||||||
|
.PHONY: clean run
|
||||||
clean:
|
clean:
|
||||||
rm target/*
|
rm target/*
|
||||||
|
|
||||||
|
run: src/4_python.py
|
||||||
|
python target/4_python.py
|
||||||
|
|||||||
@@ -1,2 +1,17 @@
|
|||||||
# Chinese Whispers
|
# Chinese Whispers
|
||||||
A project to pass a string between as many languages as I know.
|
A project to pass a string between as many languages as I know.
|
||||||
|
|
||||||
|
Has no practical purpose, but it's interesting to see how far I can push the idea. It's also teaching me a lot about IPC.
|
||||||
|
|
||||||
|
If you know any languages not on the list, please add them! Each file should be named n_[programming language], where n is the number of the program. It should take in a string, and append "Hello from [programming language].\n". It is your resonsibility to add appropriate output IPC to the previous file, so that it can interface with your program.
|
||||||
|
|
||||||
|
Chain of messages:
|
||||||
|
|
||||||
|
1. NASM x86_64 Assembly
|
||||||
|
2. C
|
||||||
|
3. Rust
|
||||||
|
4. Python
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
- Linux x86_64
|
||||||
|
- Python interpreter
|
||||||
|
|||||||
+13
-3
@@ -1,5 +1,8 @@
|
|||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::ffi::c_char;
|
use std::ffi::c_char;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::fs::*;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -7,9 +10,9 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), String> {
|
fn main() -> Result<(), String> {
|
||||||
|
// Get input string
|
||||||
let raw_string_pointer: *const c_char = unsafe { _2_c_func() };
|
let raw_string_pointer: *const c_char = unsafe { _2_c_func() };
|
||||||
if raw_string_pointer.is_null() {
|
if raw_string_pointer.is_null() { return Err(String::from("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
|
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
|
// string is null terminated since we created it ourselves in a previous program. However, if
|
||||||
@@ -20,8 +23,15 @@ fn main() -> Result<(), String> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut string = String::from(string);
|
let mut string = String::from(string);
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
string.push_str("Hello from Rust.");
|
string.push_str("Hello from Rust.");
|
||||||
println!("{}", string);
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
|
||||||
|
let pipe_path = &Path::new("chinese_whispers_pipe");
|
||||||
|
let mut file = File::create(pipe_path).expect("Couldn't open pipe!");
|
||||||
|
file.write(string.as_bytes()).expect("Couldn't write to pipe!");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# adapted from https://stackoverflow.com/a
|
||||||
|
# Retrieved 2025-12-19, License - CC BY-SA 3.0
|
||||||
|
|
||||||
|
import os
|
||||||
|
import errno
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.mkfifo('chinese_whispers_pipe')
|
||||||
|
except OSError as oe:
|
||||||
|
if oe.errno != errno.EEXIST:
|
||||||
|
raise
|
||||||
|
|
||||||
|
os.system("./target/3_rust &"); # Run 3_rust in background to start writing to pipe
|
||||||
|
|
||||||
|
with open('chinese_whispers_pipe') as fifo:
|
||||||
|
data = fifo.read()
|
||||||
|
|
||||||
|
print(data + "\nHello from Python.")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user