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头文件,编译器甚至运行预处理器,甚至像stdio的FILE*都有问题.
建议把importC声明引入全局实现定义模块中,其他类似模板插件或别名用来消歧.
该bug是ImportC的重要工具,不是玩具.
请注意,解决此问题不是针对此特定错误修复,而是完全重构C代码工作方式.
浙公网安备 33010602011771号