javascripttauri

How can I run a C file inside a Tauri app?


I have made a C file which displays certain data using the printf command

I want to make a Tauri app to display this data. For now, I am still trying to get the data from the Tauri app. How could I do this? I would prefer not to add the C file to my app. Instead, I want to generate the executable file manually and include the executable file in my app

I have already tried multiple different methods to run the C file from within the Tauri app. However, nothing has worked.

I have tried using Tauri Sidecar to do this

I have also tried using this code:

const command = new Command('run-c-app', ['./myapp']);
const output = await command.execute();
console.log('Output:', output.stdout);

I have also tried using this code:

#[command]
fn run_c_program() -> String {
    let output = Command::new("./myapp")
        .output()
        .expect("Failed to execute C program");
    
    if output.status.success() {
        String::from_utf8_lossy(&output.stdout).to_string()
    } else {
        String::from_utf8_lossy(&output.stderr).to_string()
    }
}

I am using the following package versions:

@tauri-apps/api: 2.8.0
@tauri-apps/plugin-opener: 2.5.0
react: 19.1.1
react-dom: 19.1.1
@tauri-apps/cli: 2.8.4
vitejs/plugin-react: 4.7.0
vite: 7.1.7

Solution

    1. Ensure your C file has a main function. This is the function which will be called
    2. Update the src-tauri/src/lib.rs file:
    use tauri::command;
    use std::process::Command;
    use std::path::PathBuf;
    
    #[command]
    fn run_c_program() -> String {
        // Use absolute path from the project root
        let mut c_program_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        c_program_path.pop(); // Go up from src-tauri
        c_program_path.push("backend");
        c_program_path.push("compiled-c-file");
        
        println!("Looking for C program at: {:?}", c_program_path);
        
        // Execute the C program and capture output
        match Command::new(&c_program_path).output() {
            Ok(output) => {
                if output.status.success() {
                    let stdout = String::from_utf8_lossy(&output.stdout).to_string();
                    println!("C program output: {}", stdout);
                    stdout
                } else {
                    let stderr = String::from_utf8_lossy(&output.stderr).to_string();
                    println!("C program error: {}", stderr);
                    format!("Error: {}", stderr)
                }
            }
            Err(e) => {
                let error_msg = format!("Failed to execute C program at {:?}: {}", c_program_path, e);
                println!("{}", error_msg);
                error_msg
            }
        }
    }
    
    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
        tauri::Builder::default()
            .plugin(tauri_plugin_opener::init())
            .invoke_handler(tauri::generate_handler![greet, run_c_program])
            .run(tauri::generate_context!())
            .expect("error while running tauri application");
    }
    
    1. Add this code to the src-tauri/tauriconf.json file:
        "plugins": {
            "shell": {
                "sidecar": {
                    "C-FILE-NAME": {
                        "path": "PATH-TO-THE-EXECUTABLE-C-FILE",
                        "args": []
                    }
                }
            }
        }
    
    1. Run the C file inside your app:
        const [cProgramOutput, setCProgramOutput] = useState("");
    
    
        async function runCProgram() {
            const output = await invoke("run_c_program");
            setCProgramOutput(output);
        }
    
        useEffect(() => {
            runCProgram();
        }, []);
    
                <div className = "row">
                    <div style = {{ "textAlign": "left", "margin": "20px", "padding": "15px", "backgroundColor": "#000000", "borderRadius": "8px" }}>
                        <h3>C Program Output</h3>
                        <pre style = {{ "whiteSpace": "pre-wrap" }}>{cProgramOutput || "Loading..."}</pre>
                        <button onClick = {runCProgram}>Run C Program Again</button>
                    </div>
                </div>