Hi, my problem is that FFI works on ubuntu but doesn't work on alpine. I develop my algorithm on Ubuntu, and once I implement a new feature, I package it into an Alpine container(based on rust:alpine3.22). I implement the solver in C++, and the server is built using Rust. The server receives network requests and then calls the C++ solver to process them.
I used to use CLI, and my solver on Alpine worked fine. But today, I replaced the CLI with FFI. The Rust server transmits C-style strings as parameters to the C++ solve
function. It works fine on Ubuntu, successfully solving the problem and printing the solution. However, when I package the program into the Alpine container, it runs successfully until it transmits the parameters to the C++ function. My program is able to print "calc begin", but then it doesn't proceed. Then it throw Segmentation fault instead of print "read problem". So I suspect the issue occurs when transmitting the parameters.
Rust
use crate::request_data::ToProblem;
use crate::response::response_v3::ResponseV3;
use crate::CliError;
use crate::request_data::request_data_v3::RequestDataV3;
use crate::response::Response;
use libc::{c_char, c_void};
use std::ffi::{CStr, CString};
unsafe extern "C" {
fn solve(problem_string: *const c_char, config_string: *const c_char)->*mut c_void;
fn get_c_str(result:*mut c_void)->*const c_char;
fn free_result(result:*mut c_void);
}
pub async fn handle_request(data: RequestDataV3) -> Result<warp::reply::Json, warp::Rejection> {
println!("start handle");
let problem_string=serde_json::to_string(&data.to_problem()).unwrap();
let config_string=serde_json::to_string(&data.config).unwrap();
let problem_cstr = CString::new(problem_string).unwrap();
let config_cstr = CString::new(config_string).unwrap();
println!("{:?}",problem_cstr);
println!("{:?}",config_cstr);
let solution;
println!("calc begin");
unsafe {
let result=solve(problem_cstr.as_ptr(), config_cstr.as_ptr());
println!("calc end");
solution = CStr::from_ptr(get_c_str(result)).to_string_lossy().into_owned();
println!("get string");
free_result(result);
println!("free");
}
let solution_json = serde_json::from_str(&solution);
if let Err(e) = solution_json{
return Err(warp::reject::custom(CliError(e.to_string())));
}
let solution_json=solution_json.unwrap();
let response = Response {
solution:solution_json,
};
let response_v3=ResponseV3::from_response(&data, response);
Ok(warp::reply::json(&response_v3))
}
C++
#include <solver.hpp>
extern "C"{
struct Result{
std::string result;
};
Result* solve(const char * problem_string,const char * config_string){
std::cout<<"read problem"<<std::endl;
SolverConfig config(json::parse(config_string));
json problem_json=json::parse(problem_string);
Problem problem(problem_json);
std::cout<<"solve"<<std::endl;
Solver solver(&problem,config);
Solution solution=solver.solve();
std::cout<<"return"<<std::endl;
Result* result=new Result();
result->result=solution.to_json().dump();
return result;
}
const char* get_c_str(Result* result) {
return result->result.c_str();
}
void free_result(Result* result) {
delete result;
}
}
2 posts - 2 participants
Read full topic
🏷️ Rust_feed