77人参与 • 2026-02-08 • rust
#[no_mangle]extern "c"
// lib.rs
#[no_mangle]
pub extern "c" fn add_numbers(a: i32, b: i32) -> i32 {
a + b // 简单加法逻辑
}
// main.cpp
extern "c" int add_numbers(int, int);
int main() {
return add_numbers(3, 4); // 返回7
}
i32int
repr(c)确保rust结构体内存布局与c一致*const u8与长度组合cargo build --release生成libmylib.amylib.h)g++ main.cpp -lmylib -lstdc++ -lpthread -ldl| 机制 | 说明 |
|---|---|
| 返回码 | rust函数返回result编码为整型状态 |
| 函数指针回调 | c++传递函数指针给rust,实现事件通知 |
extern "c"
extern "c" {
void log_message(const char* msg);
int add_numbers(int a, int b);
}
log_messageadd_numbers
[lib] crate-type = ["staticlib", "cdylib"]
#[no_mangle]
pub extern "c" fn add_numbers(a: i32, b: i32) -> i32 {
a + b
}
target/release/目录extern "c"声明对应函数原型// 将字符串与基本类型封装为安全结构体
type safedata struct {
value string `json:"value"`
type string `json:"type"` // "int", "float", "bool"
}
// 序列化前验证类型一致性
func encodebasictype(v interface{}) (string, error) {
var data safedata
switch val := v.(type) {
case int:
data = safedata{value: fmt.sprintf("%d", val), type: "int"}
case bool:
data = safedata{value: fmt.sprintf("%t", val), type: "bool"}
default:
return "", errors.new("unsupported type")
}
jsonbytes, _ := json.marshal(data)
return string(jsonbytes), nil
}
int write_data(int fd, const char* buf, size_t len); // 返回0表示成功,-1表示失败,错误原因存储于全局errno
| 字段 | 含义 |
|---|---|
| status | 错误码枚举(success/io_error/invalid_param) |
| data | 有效返回数据指针 |
| message | 可选错误描述字符串 |
[lib] crate-type = ["cdylib"] [dependencies] aes-gcm = "0.10"
use aes_gcm::{aes256gcm, key, nonce};
use std::os::raw::c_uchar;
#[no_mangle]
pub extern "c" fn encrypt(
key: *const c_uchar,
nonce: *const c_uchar,
plaintext: *const c_uchar,
plaintext_len: usize,
ciphertext: *mut c_uchar,
) -> bool {
// 安全解引用指针并执行加密
}
let data = box::new(42); let raw_ptr = box::into_raw(data); // 转移所有权至 c++ // 传递 raw_ptr 给 c++,由 c++ 负责释放
class filehandle {
file* fp;
public:
explicit filehandle(const char* path, const char* mode) {
fp = fopen(path, mode);
if (!fp) throw std::runtime_error("cannot open file");
}
~filehandle() { if (fp) fclose(fp); }
file* get() const { return fp; }
};
跨语言场景下的实现示例(go + c)
//export retainobject
func retainobject(handle uintptr) {
obj := handletoobject[handle]
obj.refcount++
}
//export releaseobject
func releaseobject(handle uintptr) {
obj := handletoobject[handle]
obj.refcount--
if obj.refcount == 0 {
delete(handletoobject, handle)
freecmemory(obj.cptr) // 释放c侧内存
}
}
常见陷阱与建议
register_callback 接口,接受函数指针extern "c" 函数传递给 c++extern "c" void register_callback(void (*cb)(int)) {
// 存储函数指针
g_callback = cb;
}
extern "c" fn rust_callback(value: i32) {
println!("received from c++: {}", value);
}
关键步骤
extern "c" {
object* create_object();
void call_method(object* obj);
void destroy_object(object* obj);
}
extern "c" {
fn create_object() -> *mut c_void;
fn call_method(obj: *mut c_void);
fn destroy_object(obj: *mut c_void);
}
核心组件设计
| 组件 | 职责 | 示例技术 |
|---|---|---|
| 生产者 | 发布事件到交换机 | go 应用 |
| 中间件 | 路由与持久化消息 | rabbitmq |
| 消费者 | 订阅并处理事件 | python 服务 |
代码实现示例
// go 发布者示例
conn, _ := amqp.dial("amqp://guest:guest@localhost:5672/")
ch, _ := conn.channel()
ch.publish(
"events_exchange", // 交换机名
"user.created", // 路由键
false, false,
amqp.publishing{
contenttype: "application/json",
body: []byte(`{"id":1,"name":"alice"}`),
})
接口设计:c语言兼容abi
#[no_mangle]
pub extern "c" fn parse_log_entry(raw: *const u8, len: usize) -> logparseresult {
// 安全地从c指针构建切片
let data = unsafe { std::slice::from_raw_parts(raw, len) };
// 使用nom进行零拷贝解析
match log_parser(data) {
ok((_, parsed)) => logparseresult::success(parsed.level, parsed.msg),
err(_) => logparseresult::failure(),
}
}
性能对比
| 方案 | 吞吐量 (mb/s) | 内存安全缺陷数 |
|---|---|---|
| c++原生 | 1200 | 3 |
| rust主导 | 1150 | 0 |
| 框架 | qps | 平均延迟 | 内存占用 |
|---|---|---|---|
| gin | 89,432 | 112ms | 45mb |
| net/http | 52,107 | 198ms | 78mb |
| beego | 38,921 | 256ms | 112mb |
生产环境配置建议
优化中间件调用链
// 使用轻量级日志中间件替代 full-stack logger
func lightweightlogger() gin.handlerfunc {
return func(c *gin.context) {
start := time.now()
c.next()
// 仅记录关键指标
log.printf("%s %s %v", c.request.method, c.request.url.path, time.since(start))
}
}
到此这篇关于c++调用rust的5种方式小结的文章就介绍到这了,更多相关c++调用rust内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论