d不同翻译单元不等效

如果使用两个包含共同标头类型的C标头,则会这样.考虑以下文件:

// foo_def.h
typedef struct Foo *FooRef;

// maker.h
#include "foo_def.h"
FooRef make_foo(void);

// freer.h
#include "foo_def.h"
void free_foo(FooRef foo);

预处理为:

// maker.i
typedef struct Foo *FooRef;
FooRef make_foo(void);

// freer.i
typedef struct Foo *FooRef;
void free_foo(FooRef foo);

然后D程序中使用它:

// use_foo.d
import maker;
import freer;

void do_foo(){
    FooRef f = make_foo(); // use_foo.d(5)
    free_foo(f);           // use_foo.d(6)
}
//`maker.FooRef`与`freer.FooRef`冲突

目前可通过在大翻译单元中,包含两个C标头,然后导入来解决,但如果编译器,可理解它们是相同类型C声明,就更好了.

我考虑调整编译器,这样,导入C相同名应有相同类型.可惜,D编译器是围绕类型设计的,如果类型有相同地址,则它们相同的.改变它非常困难,且会损害速度.
但是有个可合格的从D访问的方法,因此:

import maker;
import freer;

void do_foo(){
    auto f = cast(freer.FooRef)make_foo();
    free_foo(f);
}

ImportC中这样有点棘手,因为C没有限定名:

__import maker;
__import freer : FooRef;

void do_foo(){
    FooRef f = (FooRef)make_foo();
    free_foo(f);
}

创建合并重复声明D文件更进一步:

import maker;
import freer;

alias FooRef = maker.FooRef;
extern (C) void free_foo(FooRef foo);

然后导入该模块.这是有效的,因为free_foo()声明会成功链接free_foo()定义,因为C名混杂不会混杂类型.D代码ImportC代码都可导入该合并D文件.

因此,标记为WONTFIX,因为它太具破坏性,且替代方法还不错.

如果目标无缝导入C,只需导入c头文件,编译器甚至运行预处理器,甚至像stdioFILE*都有问题.

建议把importC声明引入全局实现定义模块中,其他类似模板插件别名用来消歧.

bugImportC的重要工具,不是玩具.
请注意,解决此问题不是针对此特定错误修复,而是完全重构C代码工作方式.

posted @   zjh6  阅读(14)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示