d亚当替换工厂模式

news/2024/7/21 21:59:51 标签: d, 静态数据, 链接节, 工厂模式
du_pl"> <div id="article_content" class="article_content clearfix"> <div id="content_views" class="markdown_views prism-atom-one-light"> display: none;"> d" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">

d="_1">对象工厂替代方案

一般,需要无需用de>模块构造器de>触发de>d运行时de>的de>挑剔循环检测de>的方法来de>注册de>工厂.很多时候,de>混合模块de>构造器正是de>想要de>方法,但它有全局de>全开或全闭de>的de>循环de>检测算法.
de>全局de>关闭它,请在de>Mainde>文件中,添加以下de>代码行de>:

de class="prism language-cpp">d">extern(C) __gshared string[] rt_options = ["oncycle=ignore"];
de>

de>运行de>程序时传递de>--DRT-oncycle=ignorede>开关.
但是,如果正在de>制作de>库,则可能不想de>全局de>关闭它,因为会de>破坏de>事物.你想要更de>局部de>的方法.
唉,de>Dde>当前的模块de>构造器de>没有提供在局部说"de>这很好,相信我de>"的方法.可在de>模块信息de>构造器列表中添加de>新数组de>来实现它,根据是否de>标记de>循环de>安全de>,来分离它们.

目前,编译器de>组合de>模块的所有静态de>构造器de>到一个调用所有de>构造器de>的de>生成函数de>中.然后de>ModuleInfode>引用此de>生成函数de>,以便初化时de>druntimede>调用它.需要de>两个de>生成函数,一个de>取de>当前行为,另一个顺序无关de>运行de>.

应该de>添加de>它到语言中.

但是今天可做什么呢?
好吧,用de>ldcde>或de>gdcde>,可在自定义de>链接器节de>中放de>引用函数de>,如果看看de>ModuleInfode>实现,它也是这样.(在某些平台上,它查找de>可执行de>文件中的de>.minfode>节,在其他平台上,它发出调用特定的de>D注册de>函数的de>crt构造器de>).但是de>crt构造器de>如何实现的呢?通过带de>指针de>的de>链接器节de>!

事实上,用de>crt构造器de>是一个可能.发出其中一个,它会构建de>一个列表de>,然后稍后从de>普通D模块构造器de>调用该列表.不过,必须小心从de>crt构造器de>调用的内容,de>-druntimede>已出来了,甚至de>C运行时de>的其他de>部分de>,可能还没有完全初化,可能还有de>共享库加载锁de>.
有个de>优先级编号de>,但D禁止你设置de>该编号de>.即使你可以设置,它也不能de>解决de>所有问题.我相信当前的de>实现de>确实可让你侥幸调用de>reallocde>,所以这是可de>相当安全de>构建列表方式.只要不乱搞,你没事.

但,我想de>深入de>链接器节.转储代码:

de class="prism language-cpp">d">module dule">sections.demo;
d">import dule">core.internal.elf.io;
d">import dule">sections.demo2;

//用此注册处理器
mixin d">template Register(alias fn) {
    d">import dule">ldc.attributes;
    @section(".mytest") __gshared d">void function() registered = &fn;
}

//必须注册`挂名`来欺骗链接器,在此搞一个
d">void specialCtor() {
    d">import dule">std.stdio;
    writeln("hello special ctor");
}
mixin Register!specialCtor;

// impl来取它
alias SectionDataHandler = d">void function(scope d">const(ubyte)[] data);

d">int findSectionInfo(SectionDataHandler handler) {
    d">import dule">core.internal.elf.dl;
    SharedObject exe = SharedObject.thisExecutable();

    ElfFile file;
    d">if(!ElfFile.open(exe.name.ptr, file))
        d">return 1;

    foreach(index, name, sectionHeader; file.namedSections) {
        d">if(name == ".mytest") {
            d">if(d">auto offset = sectionHeader.shdr.sh_addr) {
                d">auto beg = exe.baseAddress + offset;
                d">auto size = sectionHeader.shdr.sh_size;
                d">auto data = beg[0 .. size];
            //愚蠢无用的`NOGC`限制我,仅当体为`NOGC`,可标记`NOGC`
                alias BypassAttribute = d">void function(scope d">const(ubyte)[]) @nogc nothrow;
                (cast(BypassAttribute) handler)(cast(ubyte[]) data);
            } d">else {
                // 未映射
            }
        }
    }
    d">return 0;
}

d">void main() {
    d">import dule">std.stdio;

    // 从列表中调用函数
    d">static d">void handler(scope d">const(ubyte)[] data) {
    //必须引用`神奇节`中的一个变量,否则`--gc-sectionsarg`默认链接器会去掉它!
        d">auto reference = registered;
        reference();
        d">auto fns = cast(d">void function()[]) data;
        foreach(fn; fns) {
            // 不要重复调用根引用
            d">if(fn is reference)
                d">continue;
            fn();
        }
    }

    writeln(findSectionInfo(&handler));
}
de>

还有第二个de>文件de>注册了:

de class="prism language-cpp">d">module dule">sections.demo2;
d">import dule">sections.demo;
d">void otherCtor() {
    d">import dule">std.stdio;
    writeln("here too");
}

mixin Register!otherCtor;
de>

注意,我用了de>ldc.attributesde>,所以该演示只是de>LDCde>,但de>gdc.attributesde>工作方式相同,所以可很容易地支持de>这两个de>编译器.不过,de>DMDde>现在没用.

de>编译并运行de>它(仅在de>Linuxde>上测试!也应该在de>BSDde>上运行,但de>Macde>和de>微软de>等需要进一步调整):

de class="prism language-cpp">$ ldc2 -i=core.internal.elf sections.d sections2.d  && ./sections
hello special ctor
here too
0
de>

注意,我用de>-i=core.internal.elfde>来引入该de>ElfFilede>类型.否则,不会在de>构建de>中de>包含de>它(编译器假定,因为它是de>druntimede>的一部分,它de>预编译de>在库中,但也可能没有这些指定的,加它至构建使它更易工作).

否则,只需de>基本编译和运行de>,就运行了.

在此de>基础de>上创建东西,就像如果de>注册de>了de>一个变量de>,可de>自动de>生成附加它到de>数组de>的函数.或,可设置该节自身为de>特定类型de>而不是de>函数列表de>,且直接de>不运行de>就用它;de>链接器节de>只是de>提前de>连接的de>静态数据de>,因此de>无需de>进一步操作,可de>切片de>并转换为de>另一个de>类型并用它.
甚至可这样注册de>httpde>路由等,且知道在de>可执行de>文件中de>查找de>哪个节的de>特定de>检查器,甚至可de>不运行de>程序就de>打印de>出它们!
可用de>静态数据de>做很多很酷的,de>可执行de>文件节是de>进入de>该世界的de>窗口de>.

div> div> <div id="treeSkill">div> <div id="blogExtensionBox" style="width:400px;margin:auto;margin-top:12px" class="blog-extension-box">div>

http://www.niftyadmin.cn/n/61808.html

相关文章

c# winform错误大全

c# winform 错误大全为了实现安装包安装完成后&#xff0c;启动程序。System.BadImageFormatException: 未能加载文件或程序集“file:///C:\xxxxxxxxx\xxxxxxx.exe”或它的某一个依赖项。生成此程序集的运行时比当前加载的运行时新&#xff0c;无法加载此程The version of the …

集成运放中的单元电路概念详解(二)

电流源电路一.基本电流源电路1.镜像电流源如上图所示为镜像电流源电路&#xff0c;它由两只特性完全相同的管子T0和T1构成&#xff0c;由于T0的管压降Uceo与其b-e间电压Ubeo相等&#xff0c;从而保证T0工作在放大状态&#xff0c;而不进入饱和状态&#xff0c;故集电极电流IC0β…

【C语言】可变参数列表

本篇博客让我们来认识一下C语言学习过程中往往被忽略的可变参数列表 所谓可变参数&#xff0c;就是一个不限定参数数量的函数&#xff0c;我们可以往里面传入任意个数的参数&#xff0c;以达成某些目的。 关联&#xff1a;C11可变模板参数&#xff1b;本文首发于 慕雪的寒舍 …

数据库(第一天)

文档信息 文档类别正式文档文档编号数据库基础课 1.2-001版本1.2-001文档名称数据库基础课编写负责人/编写时间梁昭东/2023 年 1 月 30 日审核负责人/审核时间年 月 日批准人/批准时间年 月 日 变更记录 日期版本号变更内容修订者2023.01.30v1.2版根据实际情况增删了部分内容…

vue3 Proxy响应式原理分析(面试题)

在开始正文前&#xff0c;先理一下vue2 Object.defineProperty 和 vue 3 Proxy 区别&#xff1a; Object.defineProperty&#xff1a;数据劫持 Proxy&#xff1a;数据代理 注意&#xff1a; 响应式原理和双向数据绑定原理是两回事&#xff0c;一般面试官会先问响应式原理再问双…

SQL注入Getshell的奇思妙想(下)

前言 由于笔者发现大量的hr面试官都喜欢从SQL注入开始询问&#xff0c;所以留心了一下关于SQL注入的问题的频率。结果非常amazing啊&#xff01;不出意外的是–os- shell名列榜首。 但是啊由于我们不能被面试官所引导&#xff0c;这样太被动啦&#xff01;我们应该引导hr问我们…

linux的三权分立设计思路和用户创建(安全管理员、系统管理员和审计管理员)

目录 一、三权分立设计思路 1、什么是三权 2、三员及权限的理解 3、三员之三权 4、权限划分 5、“三员”职责 6、“三员”配置要求 二、linux三权分立的用户创建 1、系统管理员 2、安全管理员 3、审计管理员 一、三权分立设计思路 1、什么是三权 三权指的是配置、…

【C++设计模式】学习笔记(5):Decorator 装饰模式

目录 简介动机(Motivation)模式定义结构(Structure)要点总结笔记结语简介 Hello! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~ ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计算机专业,获得过国家奖学金…