原文
导入用'-betterC'
单独编译的XYZ
模块,会有因为缺少应由XYZ
模块定义的叫__ModuleInfo
的符号的链接器错误
.
一种补救
方法是在XYZ
中定义此值:
extern(C) __gshared ModuleInfo _D3dmd7backend7ptrntab12__ModuleInfoZ;
导入
模块会依次
添加所有导入模块
的引用
,参见.object.ModuleInfo
中定义的importedModules
属性的定义.
这真是问题吗?为啥要用-betterC
编译D库
,然后在D程序中
使用它?
一个用例是dmd
编译自身
.
一般,想在D中
构建可同时使用C和D
的库.
$ dmd -betterC -lib mylib1.d mylib2.d
$ dmd -I. mylib1 myexe.d -main
module myexe;
import mylib2;
module mylib1;
static this() {}
module mylib2;
import mylib1;
为什么'mylib1'
有模块构造器?,'-betterC'
不应拒绝它吗?
有人创造性
地在更好的C
模式下,用'pragma(crt_constructor)'
制作了模块构造器
.
不是只对'shared static this'
吗?
:dmd -betterC -lib mylib1.d mylib2.d
这编译mylib1.d
和mylib2.d
,并创建包含两个
文件目标代码的mylib.lib
库文件.
:dmd -I. mylib1 myexe.d -main
这会把mylib1.d
和myexe.d
编译在一起,形成mylib1.exe
的可执行
文件.因为命令行
中没有给出,它无法从mylib2.d
中找到内容.这不是编译器
错误.
我想应,创建放入mylib1.d
和mylib2.d
编译版本的mylib1.obj
:
dmd -betterC mylib1.d mylib2.d
而,
dmd -I. myexe.d mylib1.obj -main
编译myexe.d
并链接到mylib1.obj
,来创建叫myexe.exe
的可执行文件.或至少这样做,但给出:
myexe.obj(myexe)
Error 42: Symbol Undefined __D6mylib212__ModuleInfoZ
因为-betterC
抑制生成ModuleInfo
,而myexe.d
却期望它.这是编译器
错误,或至少是编译器
问题.
如果以下至少有一个为真
,模块
就会产生ModuleInfo
:1
.它导入生成ModuleInfo
模块.2
.它有个静态构造器
3
.它有静态析构器
4
.它有单元测试
声明
但如果启用了-betterC
,则会禁止
生成,本问题,是由于有静态构造器
的问题.Iain
的想法是正确
的.在-betterC
模式下,解决方法是:1
.使用以下来自动注解静态构造器
:
pragma(crt_constructor) extern (C)
2
.对静态析构器
同样3
.对(1)
和(2)
不设置'needmoduleinfo'
.
这会用C运行时库
机制运行构造器和析构器
.缺点
是按链接器
看到的目标
文件顺序,而不是深度优先
层次顺序构造和析构
.Mathias
的建议很好.在'static this()'
上给出错误,并仅在'shared static this()'
上工作.
mylib1.d
中有个静态构造器
.何时构造?
在C代码中,C
运行时按它们在链接器
中顺序来处理.
在D代码中,D
启动代码,会在C运行时
初化*之后*
按深度
优先级处理.两者
是不同的,且是不可调和
的(尽管大多数静态构造器
可能不关心顺序,但不能依赖它).myexe.d
无法知道它正在导入更好C
模块,因此它无法正确处理构造.
因此,提出另一种方法.mylib1.d
只需选择是C构造
还是D构造
.C构造
将是:
pragma(crt_constructor) extern (C) static this() {... }
而D构造
:
static this() {... }
myexe.d
在看到D静态构造器
时,需要来自mylib1.d
的ModuleInfo
.编译器在用-betterC
编译mylib1.d
时,且看到D静态构造器
时,则可为该静态构造器
创建ModuleInfo
.
为更好C和D
程序,创建更好C
库,用:
pragma(crt_constructor) extern (C) static this() {... }
D模块构造器
当然不应在betterC代码
中工作.它们可抛死码
警告,因此不需要生成ModuleInfo
(这应该很容易解决).这避免未来
意外.
然而,根本
问题是按需
付费运行时
,在-betterC
中,需要ModuleInfo
时,不能按需付费的打开
它.
现在无法打开生成ModuleInfo
,因为DllImport
不完整(实现难).如果现在开启
它,exe
与带D
的dll
运行时,会有段错误
.
应该先解决DllImport
问题,然后用此代码
作为测试用例
来验证
,是否确实修复
它,而不是先修复本漏洞
.
本例中,ModuleInfo
是D运行时
如何运行静态构造器
.用betterC
编译的程序只能与对ModuleInfo
一无所知的C运行时
库链接.
问题是编写用betterC
编译的库,并与betterC
程序或D程序
链接.
简单关闭生成ModuleInfo
,表明betterC
的库不运行
它的静态构造器
.
由于导入betterC
模块的D程序
不知道它们是否是betterC
模块,因此betterC
模块选择如何静态
构造.
即,更好C
模块应用以下
代码来运行其静态构造
:
pragma(crt_constructor) extern (C) void doMyStaticConstruction() {... }
如果更好C
只与D主
连接,它应该:
static this() {... }
但不应同时执行这两个
操作,因为如果同Dmain
链接,则静态
构造了两次.
修复该错误报告的改变是,对betterC
模块,如果有'static this'
构造器就生成ModuleInfo
,并在文档
中添加这些指令
.导出DLL
是个正交
问题.
这不应
是自动的.-betterC
是一个开关
的集合.其中之一是关闭生成ModuleInfo
.这是它在LDC
和GDC
中的工作
方式.
它需要通过开关
选入.否则,可能会有意外
.
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
当前文章:d导入更好C的链接器错误-创新互联
地址分享:http://scgulin.cn/article/epecd.html