Can Rust Communicate with a C Program Using gRPC? A Rust Client and C Server Example

Yes, Rust can communicate with a C program using gRPC. gRPC is a language-agnostic framework that enables interoperability between different languages, including Rust and C.

Key Steps Overview:

  1. Define the gRPC Interface (.proto File): Specify the interface betwean the cleint and server.
  2. Implement the C Server: Use C to handle requests from the client.
  3. Implement the Rust Client: Use Rust to call the server's interface.

Step 1: Define the gRPC Interface

Create a helloworld.proto file to define the service and messages:

syntax = "proto3";

package helloworld;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloResponse);
}

message HelloRequest {
  string name = 1;
}

message HelloResponse {
  string message = 1;
}

Step 2: C Language Server Implementation

First, convert the .proto file in to C-compatible code.

  1. Install gRPC and Protobuf Tools:

    • Install the gRPC C library and Protocol Buffers compiler.
  2. Generate C Code:
    Use the protoc compiler to generate C code:

    protoc --grpc_out=. --plugin=protoc-gen-grpc=/usr/local/bin/grpc_cpp_plugin helloworld.proto
    protoc --cpp_out=. helloworld.proto
    
    
  3. **C Server Code:**Implement the server in C (assuming the generated files are helloworld.grpc.pb.c and helloworld.pb.c):

#include <grpc/grpc.h>
#include <grpc/impl/codegen/status.h>
#include <grpc/pprof.h>
#include <helloworld.grpc.pb.h>
#include <stdio.h>
#include <string.h>

void SayHello(grpc_server *server, grpc_context *ctx, grpc_call *call) {
    HelloRequest req;
    HelloResponse res;
    
    // Read request data
    grpc_call_read(call, &req);
    
    // Construct response message
    const char *response_msg = "Hello, ";
    snprintf(res.message, sizeof(res.message), "%s%s!", response_msg, req.name);
    
    // Send response
    grpc_call_send_response(call, &res);
}

int main(int argc, char **argv) {
    grpc_server *server = grpc_server_create();
    
    grpc_server_add_service(server, &Greeter_service);
    
    grpc_server_start(server, "localhost:50051");
    
    printf("Server started, listening on 50051\n");
    grpc_server_run(server);  // Blocking, will wait until terminated
    return 0;
}

Step 3: Rust Client Implementation

  1. **Add Dependencies:**Add tonic and prost to your Cargo.toml:

    [dependencies]
    tonic = "0.6"
    prost = "0.10"
    tokio = { version = "1", features = ["full"] }
    
    
  2. Generate Rust Code:
    Use prost and tonic to generate Rust code from the .proto file.

    In build.rs, specify the generation:

    fn main() {
        tonic_build::compile_protos("proto/helloworld.proto")
            .unwrap_or_else(|e| panic!("Failed to compile protos {:?}", e));
    }
    
    

    Then create proto/helloworld.proto and run:

    cargo build
    
    

    This generates the Rust code.

  3. **Rust Client Code:**Implement the client in main.rs:

use tonic::transport::Channel;
use helloworld::greeter_client::GreeterClient;
use helloworld::HelloRequest;

pub mod helloworld {
    tonic::include_proto!("helloworld");
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = GreeterClient::connect("http://localhost:50051").await?;

    let request = tonic::Request::new(HelloRequest {
        name: "World".into(),
    });

    let response = client.say_hello(request).await?;

    println!("RESPONSE={:?}", response.into_inner().message);

    Ok(())
}

Step 4: Run the Server and Client

  1. **Run the C Server:**Compile and run the C server:

    gcc -o server server.c -lgrpc++ -lprotobuf
    ./server
    
    

    This starts a gRPC server listening on localhost:50051.

  2. **Run the Rust Client:**Run the client in your Rust project:

    cargo run
    
    

    The client sends a request via gRPC to the server, which processes it and returns a response. The client then prints the result.

Summary:

By following these steps, you can enable communication between a Rust client and a C server using gRPC. gRPC allows for seamless interaction between different programming languages through its protocol definition in .proto files.

If you have any issues or need further assistance, feel free to ask!

Tags: gRPC C rust Protobuf interoperability

Posted on Thu, 03 Sep 2026 16:47:42 +0000 by PoOP