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

在Rust调用C函数时,能否用Option/NonNull处理指针?

问题

我在Windows平台下调用一个接收结构体指针的C函数,该结构体定义如下:

typedef struct {
    uint32_t *field;
} Foo;

void bar(Foo *foo);

由于NonNull自Rust 1.29版本起具有repr(transparent)特性,我考虑采用如下Rust表示方式:

use std::ptr::NonNull;

#[derive(Default)]
#[repr(C)]
struct Foo {
    field: Option<NonNull<u32>>,
}

extern "system" {
    fn bar(foo: Option<NonNull<u32>>);
}

请问上述写法是否可行,还是必须使用*mut来定义指针?


回答

你的写法部分可行但存在关键错误,具体分析如下:

  • 结构体Foo的定义是可行且推荐的
    因为NonNull<T>具有repr(transparent),内存布局和*mut T完全一致;而Rust会将Option<NonNull<T>>优化为与*mut T相同的内存大小(用空指针表示None,非空指针表示Some),和C中uint32_t*的布局完全匹配。这种写法既能保证C交互的内存兼容性,又能利用Rust类型系统避免空指针的不安全操作,比直接用*mut u32更安全。

  • extern块中bar的函数签名完全错误
    C函数bar接收的是Foo*类型参数,但你写的Rust签名将参数定义为Option<NonNull<u32>>,与C端类型完全不匹配。正确的签名应该是接收*mut Foo或者Option<NonNull<Foo>>:

    extern "system" {
        fn bar(foo: *mut Foo);
        // 也可以用Option<NonNull<Foo>>,同样能安全处理空指针场景
        // fn bar(foo: Option<NonNull<Foo>>);
    }
    

总结:结构体字段用Option<NonNull<u32>>是可行的,但必须修正bar的函数签名,使其匹配C端的Foo*类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 20:43:14