You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust动态库中调用C++应用的Core类?

在Rust动态库中调用C++ Core类的实现方案

1. 修正Rust中的Core类型定义与全局实例存储

Rust中的不透明结构体无需#[repr(C)],我们仅用它标记C++ Core类的指针类型,不需要依赖其内部布局:

// 不透明结构体,仅用于标识C++ Core类的指针类型
pub struct Core;

// 全局存储C++传入的Core实例指针
// 注意:static mut是非线程安全的,单线程环境可直接使用;多线程需加锁(比如用Mutex)
static mut CORE_INSTANCE: Option<*mut Core> = None;

2. 实现初始化函数(供C++调用)

初始化函数的参数类型对应C的Core*,需添加#[no_mangle]禁止Rust编译器修改函数名,保证C能正确寻址:

#[no_mangle]
pub extern "C" fn init_core(core_instance: *mut Core) {
    unsafe {
        CORE_INSTANCE = Some(core_instance);
    }
}

3. 调用C++类的成员函数

由于C++成员函数隐含this指针,调用约定与普通C函数不同,有两种可行方案:

方案一:C++提供C风格包装函数(推荐,安全且跨编译器)

在C++代码中为printMessage编写C兼容的包装函数,将this指针显式作为参数传入:

extern "C" {
    void core_print_message(Core* core, const char* text, int length) {
        core->printMessage(text, length);
    }
}

然后在Rust中声明并调用该函数:

// 声明C++导出的包装函数
extern "C" {
    fn core_print_message(core: *mut Core, text: *const u8, length: i32);
}

fn foo() {
    unsafe {
        if let Some(core) = CORE_INSTANCE {
            // C++需要以'\0'结尾的字符串,这里用b"Hello\0"生成符合要求的字节序列
            core_print_message(core, b"Hello\0".as_ptr(), 5);
        }
    }
}

方案二:直接调用C++成员函数(unsafe,依赖编译器实现)

这种方式无需修改C++代码,但依赖编译器对成员函数的布局实现(如GCC/Clang的调用约定),风险较高:

// 定义对应C++成员函数的函数指针类型,第一个参数为this指针
type PrintMessageFn = unsafe extern "C" fn(this: *mut Core, text: *const u8, length: i32);

fn foo() {
    unsafe {
        if let Some(core) = CORE_INSTANCE {
            // 将C++成员函数地址转换为函数指针,需替换为实际的成员函数地址
            // 成员函数地址可由C++传递给Rust,或依赖编译器布局假设(不推荐)
            let print_fn: PrintMessageFn = std::mem::transmute(0x12345678);
            print_fn(core, b"Hello\0".as_ptr(), 5);
        }
    }
}

注意:不同编译器(如MSVC与GCC)的成员函数调用约定可能不同,这种方式易触发未定义行为,仅在无法修改C++代码时使用。

4. C++侧调用示例

在C++中初始化Core实例,并调用Rust的初始化函数:

#include <iostream>

class Core {
public:
    void printMessage(const char* text, const int length) {
        std::cout << std::string(text, length) << std::endl;
    }
};

// 声明Rust导出的初始化函数
extern "C" void init_core(Core* core);

int main() {
    Core core;
    init_core(&core);
    
    // 触发Rust中的foo函数调用(需Rust导出对应触发函数)
    return 0;
}

内容的提问来源于stack exchange,提问作者Darimity

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 12:35:15