d导出的讨论
原文
以下是导出
的所有问题的列表:32
位和64
位问题:
1)
导出全局
变量会产生链接器
错误
2)
导出线本
变量应该是错误(至少在C++
中是这样)(.1)
3)
应在模块有导出符号
后立即导出模块信息
.
4)
不导出类的__gshared
成员
5)
,未导出TestClass
的TypeInfo
对象
6)
,未导出TestStruct
的TypeInfo
对象
请见随附复制案例.如果此重现
案例实际编译并运行dll
.应可支持共享运行时
.
也应该导出导出符号
引用的如ModuleInfos,TypeInfos,opEquals
等编译器生成符号
.
.1
不,至少ELF
支持链接/访问
另一个共享库的TLS
值.
对TLS
访问,窗口
还使用每个DLL
的索引
,因此应该可链接/重定位
它们.
问题似乎
是导出使用类似C
的规则来区分声明和定义
.对声明
,导出表明__declspec(dllimport)
,对定义,导出表明__declspec(dllexport)
.
export void foo(); // 当作导入
export void foo() {} // 当作导出
要导出
全局变量,需要初化器
.
export __gshared int bar; //当作导入
export __gshared int bar = 0; //当作导出
该规则
没有意义,因为它是定义变量
并默认初化
.
要标记仅声明
,应用外(extern)
.
此外,此行为总是需要包含导入
模块声明的头文件
.
1)
导出全局变量会使链接器错误,由#10059漏洞
修复.
2问题
,不能链接到包含线本
变量定义的DLL
吗?
3问题
,符号,对我,很有意义.
如果导出用户定义类型
,则也应导出
所有编译器生成的元数据,vtables,TypeInfo,RTInfo!Type
等.
如果导出UDT
,并不肯定导出
是否表明导出
所有成员.
要在druntime/phobos
中添加导出注解,需要修复922
错误.
变量?抱歉,不确定是否可使线本
变量跨dll
边界工作,所以应先让它成为错误
,以后再允许
它.
一些随机
评论:
0,对静态和动态
链接,想用相同代码时,不可用"导出"
.建议根据编译开关
按模块粒度
导出每个公共符号
.
1,但是,不能简单
判断是从静态库
还是动态库
导入模块
中的符号
.但该区别
是必要的,因为两种情况下,代码不同.也许模块级
的版本
指示可控制
它.
2,可用其他DLL
中的TLS
变量,但当前
工具链可能不行.需要导出的是TLS
节中符号
偏移,及导出
符号DLL
中_tls_index
变量地址
.然后如下读取变量:
mov EAX,[_imp_variable.tls_index];
//读导入表中`tls_index`的地址
mov EAX,[EAX]; //读`DLL`的`tls_index`
mov EBX,FS:[2C]; // tls_array
mov EBX,[EBX+4*EAX]; // `dll`的tls_start
mov ECX,[_imp_variable.offset];
//读`DLL`的`TLS`中变量的偏移
mov EDX,[EBX+ECX];//读变量
如果不可导出偏移,则DLL
也需要_tls_start
.
对每个只返回
变量值地址的TLS
变量,实现getter
函数,不是更容易吗?
你是对的,函数
会更简单.由于间接
跳转,效率
可能稍低,但避免
了通过导入表
的两次间接
访问数据.
没有混淆保护
和导出.如,可拆分库
为两个DLL
,此时,可能需要导出/导入
,私和包
保护符号
.
通过静态库
,访问
链接变量时,编译器会生成直接访问
.但是,如果通过动态库链接
,则编译器会通过导入表
通过直接引用_imp_
符号而不是原始符号
来,生成另一级间接
.也即,编译器必须知道符号
是从动态库
还是静态库
中导入.
访问
数据时,添加了些额外重定位
数据来实现类似"自动导入"
.启动
程序时,修复重定位
,导入表
地址.
可惜,这不适合64
位应用,因为dmd
生成的二进制文件中的重定位
仅与32
位PC
相关.不能在另一个DLL
,传地址
给变量,因为它可能在32
位到不了的64
位地址空间.
仅指的是"公共符号"
?对我一切正常,但因为禁止从另一个
模块访问,对私有
符号,不重要.
也许我对窗口
机制理解
错了,但导出
符号可以相同
.类似ELF
的PLT
,在导入
库中绑定
运行时.引用
导入符号
的代码,最后,静态
链接到导入库
.
对函数符号
,是的,这是正确
的,但如前所述,要特殊处理
数据符号.
好吧,问题是,是否可用"导出"
来注解符号,并仍然创建
静态库.
优化
很好,但Walter
表示他更喜欢经典
(另一级间接
)方式.总结:
0,导出
何时表示DLL
导入,何时表示DLL
导出.讨论提出,可用命令行开关
,对每个模块(包括子模块
)启用dllimport/dllexport
.
1,是否想要导出
所有公开符号
(C++
正摆脱它,也许也应这样)
2,是否可导出整个类/构
吗?如按导出
标记类
,导出其vtable
,类型信息,所有保护/公开函数
,静态
成员等.
3,需要导出模块
哪些信息?一旦模块,有单个导出
的函数/类/变量
,就会自动导出
吗?
目前:没有标记.但是,应该创建方法
,除非用编译器的命令行开关
指定,"导出"
应是无操作
.
当前实现有些问题:
export void foo() {} // 声明=> dllexport
export void foo(); // 定义=> dllimport
export int a = 0; // 定义=> dllexport
export int a; // 声明=> dllimport
//因为它实际上是个定义,失败
export extern int a; // 声明=> dllimport
如果能避免额外的.di
标头,那就太好了.
在Unix
上进入另一个方向.
此处有关推导
更多信息.链接,
是的,因为无法注解
编译器生成
数据.
再次请避免滥用
导出保护,因为会对未来语言扩展
带来太多问题
如:维护ABI
兼容的私有符号
,多个文件/对象
中的模块定义
,部分类
.链接
和符号保护
是根本不同的概念,应该提供
正交控制.
是的,它是隐藏
的编译器数据,可能需要链接
到ModuleInfo
及其他符号.
在既创建
,导出
符号,又从另一个DLL
导入符号的DLL
中,这不管用.别名导出.
总结
别名建议.
0,对每个导出
的函数定义,还产生_imp_funcname
别名符号.
1,对每个导出
的数据定义,产生弱链接
的T*_imp_var=&var
只读指针.
2,每当调用或访问
导出符号时,使用_imp_*
符号完成
操作.
3,此类
代码与导入库
链接时,同DLL
正确工作.
4,代码
与静态库
链接时,引用
正确的定义.
5,简单导出
属性,可满足所有用例,不用担心dllimport/dllexport/无操作
.
6,如果可用整个程序优化
,则链接器
可在静态链接
时,优化额外间接寻址
的访问
数据.
最后一点不重要,因为导出
数据很少,且不好.
此外,这仅适合不应成为性能
热点的API
边界.
对ELF
导出,只需使符号
可见,否则默认
应隐藏
符号.
Mach-O
的想法?和ELF
一样?
你想用"导出"
来注解
所有火卫一
和druntime
来构建共享
版本吗?已在注解
地狱中,有nothrow
,纯,@safe
等
是的,这就是意图.手动
这样很重要,因为导出
符号,表明致力于ABI
稳定性,这应该是长期目标
.
由于导出符号是库
的已知入口
,有了是否更多推导非导出
符号问题.
dmd
很可能不能用微软
链接器的LTO
.
此外,这不仅会影响API
的边界,还会影响访问
全局数据:__gshared
,共享
变量和所有编译器内置全局数据符号
,如模块信息
,类型信息
,vtables
等.
这是因为,在不知道从DLL
导入哪些
符号时,就必须对这些符号
添加间接寻址
.如果决定用别名
,必须对全局数据访问
加上额外间接级
.
完全同意.为了方便,要提供-exportall
开关.
它会起作用
.因为编译器命令行开关
会指定模块名
,所以不会转换所有导出
为dllexport
.如,如果构建火卫一
,会在命令行加上"-export std"
.这会把std
模块中导出
转换为dllexport
.
因此,对同时
导出和导入符号
的DLL
非常有效.对dllimport
,需要指定链接到共享的phobos
库时,命令行有的等效
的,如"-import std"
开关.然后可添加到默认的sc.ini
,这样用户
就不必手动
指定.
不!仅适合标记为导出
的数据.所以很清楚可导入
什么.
导出的UDT(vtable,rtti)
的元数据和带导出
成员模块的模块信息
.注意,由于窗口
不支持插入符号,因此直接从模块
内访问
数据是安全的.
拥有源码
,但不想改时,编译器开关
有意义.
提供-export=public,package,private
可能有意义,因为没人维护ABI
.
不是vtables
,因为它们已通过类实例
间接寻址.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现