如何在Rust的FFI中使用C预处理器宏?

 极神bd韵 发布于 2023-01-30 09:53

我正在编写一些代码来连接用C编写的现有库.在我的Rust代码中,我希望能够使用来自CPP宏的值.如果我有一个C include.h,它看起来像这样:

#define INIT_FLAG 0x00000001

我希望能够像Rust一样在Rust中使用它:

#[link(name="mylib")]
extern {
    pub static init_flag: c_int = INIT_FLAG;
}

我查看了其他FFI代码,我看到很多人在Rust中复制这些值而不是从FFI中获取它们.这似乎有点脆弱,我也希望能够处理通过CPP宏定义的更复杂的事情.运行cpp我的Rust文件只有在我确定我的CPP宏仅用于简单的事情时才有效.

2 个回答
  • 这是不可能的,我认为将来不可能.C宏给它们带来了太多问题.如果要运行cppRust源,可以手动执行.

    如果您不想这样做并且如果有很多常量并且您也不想将它们的值从C代码复制到Rust,您可以创建一个C包装器,它将为这些值提供全局变量:

    #define INIT_FLAG 0x00000001
    
    ...
    
    const int init_flag = INIT_FLAG;
    

    您编译此文件,从中创建一个静态库并像往常一样链接到它:

    $ gcc -c init_flag.c
    $ ar r libinitflag.a init_flag.o
    

    锈源:

    use std::libc;
    
    #[link(name="initflag", kind="static")]
    extern {
        pub static init_flag: libc::c_int;
    }
    

    Rust源几乎与您尝试实现的完全相同.但是,您将需要C glue对象文件.

    2023-01-30 09:56 回答
  • 这仅仅是不可能的,因为C宏常量在运行时不表示任何对象或实体.这是因为cpp预处理器甚至在编译之前就执行宏扩展(并处理其余指令).请考虑以下代码段:

    #define INIT_FLAG 0x00000001
    
    /* some code */
    
    unsigned dummy() { return INIT_FLAG; }
    
    /* some other code */
    

    cpp在代码片段上运行会生成预处理代码(所谓的编译单元翻译单元),其中所有代码都INIT_FLAG被文字替换0x00000001:

    unsigned dummy() { return 0x00000001; }
    

    然后编译单元被编译,产生目标文件,但现在没有任何痕迹INIT_FLAG.因此,INIT_FLAG在链接目标文件时无法引用:它只是不包含此类符号.

    2023-01-30 09:56 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有