热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

d导入更好C的链接器错误

原文导入用-betterC单独编译的XYZ模块,会有因为缺少应由XYZ模块定义的叫__ModuleInfo的符号的链接器错误.一种补救方法是在XYZ中定义此值:extern(C)

原文
导入用'-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 -mainmodule 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.dmylib2.d,并创建包含两个文件目标代码的mylib.lib库文件.

:dmd -I. mylib1 myexe.d -main

这会把mylib1.dmyexe.d编译在一起,形成mylib1.exe可执行文件.因为命令行中没有给出,它无法从mylib2.d中找到内容.这不是编译器错误.

我想应,创建放入mylib1.dmylib2.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.dModuleInfo.编译器在用-betterC编译mylib1.d时,且看到D静态构造器时,则可为该静态构造器创建ModuleInfo.
更好C和D程序,创建更好C库,用:

pragma(crt_constructor) extern (C) static this() { ... }

D模块构造器当然不应在betterC代码中工作.它们可抛死码警告,因此不需要生成ModuleInfo(这应该很容易解决).这避免未来意外.
然而,根本问题是按需付费运行时,在-betterC中,需要ModuleInfo时,不能按需付费的打开它.
现在无法打开生成ModuleInfo,因为DllImport不完整(实现难).如果现在开启它,exe带Ddll运行时,会有段错误.
应该先解决DllImport问题,然后用此代码作为测试用例验证,是否确实修复它,而不是先修复本漏洞.

本例中,ModuleInfoD运行时如何运行静态构造器.用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.这是它在LDCGDC中的工作方式.
它需要通过开关选入.否则,可能会有意外.

与打开或关闭生成ModuleInfo相比,最好触发不触成ModuleInfo.
如,如果写了静态构造器,且抑制了ModuleInfo,程序仅链接但不会执行静态构造器,使程序不如期望.

进一步思考:
因为ModuleInfo(A)会在runtime中生成调用_d_so_registry,betterC代码不能生成(A).
更好C模块中有个'static this',或在更好C模块中导入带有'static this'的模块,需要ModuleInfo来保证语义.简单地关闭生成ModuleInfo,会链接程序,但运行时未运行static this,即代码不工作.
相反,betterC代码必须用pragma(crt_constructor)函数,而不是静态初化.由C运行时启动代码调用这些函数.
依赖pragma(crt_constructor)表明修复报告问题,并确保正确定义.1链接
之后是,在d运行时中,尽量用pragma(crt_constructor)替换static this.在此


推荐阅读
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了为什么在main.js中写import不会全局生效的问题,并提供了解决方案。在每一个vue文件中都需要写import语句才能使其生效,而在main.js中写import语句则不会全局生效。本文还介绍了使用Swal和sweetalert2库的示例。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 怀疑是每次都在新建文件,具体代码如下 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 本文介绍了在多平台下进行条件编译的必要性,以及具体的实现方法。通过示例代码展示了如何使用条件编译来实现不同平台的功能。最后总结了只要接口相同,不同平台下的编译运行结果也会相同。 ... [详细]
author-avatar
一加一等于贰_661
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有