Dlang 与 C 语言交互(二)

随着需求不断增加,发现好像需要更多的东西了。在官网上找不到资料,四处拼凑才有了本文的分享。

上一文(DLang 与 C 语言交互(一) - jeefy - 博客园)中说了非常简单了例子。本文试着向更高级的方法拓展。

文章链接(防止机器搬运):https://www.cnblogs.com/jeefy/p/17503853.html

链接库

对,还是它,只是这次给出更多的解决思路。

Writing Shared Libraries With D On Linux - D Programming Language 中我看到了这个命令:dmd -oflibdll.so dll.o -shared -defaultlib=libphobos2.so -L-rpath=/path/to/where/shared/library/is

其中 -L... 后面跟的东西叫做 linkflag,会在链接的时候使用。

于是对于一个程序,我们可以通过:

dmd somefiles.d -L-lsomelib -L-rpath=/additional/path/to/search/for/lib

来设置链接库。

其中 -rpath=... 的意思可以参考:GCC 中 -L、-rpath和-rpath-link的区别 - lsgxeva - 博客园

于是在我的项目 Jeefy / jimg · GitLab 中,最终的编译命令为:

dmd ./src/main.d -of=./build/main -I./src -L-L./build -L-rpath=./build -L-ljimg

编译前在 build 目录下有一个 libjimg.so 文件。

我通过此命令链接到这个库。

那么接下来的问题在于转化为我如何将多个 dlang 文件编译成一个 .so 文件。


这里设 OBJS 表示所有预编译后的文件(.o)。

有如下命令(采用的是 Makefile 的语法表达):

dmd $(OBJS) -shared -fPIC -of=libtest.so -L-lsomelib

我成功的获得了一个可以使用的库。

利用 ldd libtest.so 查看依赖,可以发现所有的 -l... 的依赖都被加入其中。

也就是说我可以把一个模块以及其依赖打包成一个 shared library 然后通过 -L-l... 来链接它。


这是唯一的方法吗?并不是的。

事实上采用 gcc/g++ 也可以。与上面类似:

gcc $(OBJS) -shared -fPIC -o libtest.so -lsomelib -DSOME_MACRO

可以得到一样的结果,并且我还可以定义一些宏传入其中。也就是说实际 gcc 可能功能更齐全。但是如果其中包含了没有预编译过.d 文件,就只能使用 dmd 达到这种效果了。


GDB

需要调试?不知道用什么调试?利用专门写给 dlang 的工具调试发现对 C 的支持不好?

于是转身向 gdb 走去。

想要打开调试功能,则需要在编译的时候加入 -g 参数。

无论是dmd还是gcc都要。之后通过 gdb 调试即可。

命令,断点什么的和一般的调试是一模一样的。不多说了。


动态加载链接库

Writing Shared Libraries With D On Linux - D Programming Language 中有众多讲解,这里提两句。

在 dlang 中加载链接库需要用到 core.sys.posix.dlfcn,这相当于 #include <dlfcn.h>。也就是说,dlang 中加载动态库的代码与 C 中几乎一模一样。

这里不妨以 dlang 加载 dlang 的库为例。

lib.d 编译为链接库,main.d 中加载。

dmd -c lib.d -fPIC
dmd -oflibtest.so lib.o -shared -defaultlib=libphobos2.so dmd -c main.d
dmd main.o -L-ltest -L-L. -defaultlib=libphobos2.so -map

-defaultlib=libphobos2.so 是否是必要的取决于链接的对象。

加上它之后的区别在于 libtest.so, main 会添加动态的对于 libphobos2.so 的依赖。可以通过 ldd 查看。也就是是静态链接和动态链接的区别。

如果是在 dlang 中加载 dlang 的库,那么是必要的,否则,会有多个 dlang 的实例在运行,产生冲突。(Otherwise, the result will be multiple instances of the D runtime conflicting with each other.

反正只要不是多个 dlang 库间调用,那么就要用 -defaultlib=libphobos2.so。反之则不用。

这里面 -map 指生成链接中的 .map 文件。具体作用请读者自行探究。

还有几个点说一下:

  • 在调用 dlopendlclose 时,会分别调用的 static this() { ... } 以及 static ~this() { ... }

  • 如果是 C 中调用 dlang,此时 libphobos2自动被打开,不需要再手动加载一次。文档原文 Note that libphobos2.so gets automatically dynamically loaded as well.

  • ....


作者有话说

有一段时间我疯狂吐槽 dlang,仅仅是因为我当时认为其对 C/C++ 的支持很烂(在尝试写 jgui 的时候),如此接近 C 系列的语言竟然这样!然后我就没有如何看 dlang 这个东西。

后来我机缘巧合之下,看到了 quandim 项目。于是我就想实现类似的功能,于是开始写 Jeefy / jimg · GitLab 接着就探索到了本文中的内容。确实机缘巧合令人惊叹。

接着发现一点中文文档都没有……全是英文。幸亏我英语不错,看这些文档还是没有问题。所以才有了这些文章。

哎,幸亏是高中生,不然真可能直接摆烂,然后放弃 dlang。

说实话,dlang 还是非常好的一种语言,虽然其 class 的内存分配是真的弱智……就不能同时 new 多个对象,一起分配空间吗 QwQ

Dlang 与 C 语言交互(二)的更多相关文章

  1. 使用C语言实现二维,三维绘图算法(1)-透视投影

    使用C语言实现二维,三维绘图算法(1)-透视投影 ---- 引言---- 每次使用OpenGL或DirectX写三维程序的时候, 都有一种隔靴搔痒的感觉, 对于内部的三维算法的实现不甚了解. 其实想想 ...

  2. 使用C语言实现二维,三维绘图算法(3)-简单的二维分形

    使用C语言实现二维,三维绘图算法(3)-简单的二维分形 ---- 引言---- 每次使用OpenGL或DirectX写三维程序的时候, 都有一种隔靴搔痒的感觉, 对于内部的三维算法的实现不甚了解. 其 ...

  3. 使用C语言实现二维,三维绘图算法(2)-解析曲面的显示

    使用C语言实现二维,三维绘图算法(2)-解析曲面的显示 ---- 引言---- 每次使用OpenGL或DirectX写三维程序的时候, 都有一种隔靴搔痒的感觉, 对于内部的三维算法的实现不甚了解. 其 ...

  4. Swift语言指南(二)--语言基础之注释和分号

    原文:Swift语言指南(二)--语言基础之注释和分号 注释 通过注释向自己的代码中注入不可执行的文本,作为你自己的笔记或提示.Swift编译器运行时会忽略注释. Swift的注释与C语言极其相似,单 ...

  5. FFI (语言交互接口(Foreign Function Interface))

    FFI(Foreign Function Interface)是用来与其它语言交互的接口, 在有些语言里面称为语言绑定(language bindings), Java 里面一般称为 JNI(Java ...

  6. #r语言(二)笔记

    #r语言(二)笔记 #早复习 #概述:R是用于统计分析.绘图的语言和操作环境 #对象: #数据类型--统称为对象 #向量(vector):用于存储数值型.字符型或逻辑型数据的一维数组. #定义向量: ...

  7. Swift5 语言指南(二十八) 高级运算符

    除了Basic Operators中描述的运算符之外,Swift还提供了几个执行更复杂值操作的高级运算符.这些包括C和Objective-C中您熟悉的所有按位和位移运算符. 与C中的算术运算符不同,S ...

  8. Swift5.1 语言指南(二十九)高级运算符

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  9. iOS开发之SQLite-C语言接口规范(二) —— Prepared Your SQL Statements

    在<SQLite的C语言接口规范(一)>中介绍了如何去连接打开数据库,本篇博客就介绍如何操作数据库,本篇主要给出了如何执行数据库查询语句(Select), 然后遍历结果集.本篇博客就直接使 ...

  10. 遗传算法的C语言实现(二)-----以求解TSP问题为例

    上一次我们使用遗传算法求解了一个较为复杂的多元非线性函数的极值问题,也基本了解了遗传算法的实现基本步骤.这一次,我再以经典的TSP问题为例,更加深入地说明遗传算法中选择.交叉.变异等核心步骤的实现.而 ...

随机推荐

  1. 手写Mybatis代码实现会出现的问题

    实现自定义框架过程中遇到的问题及解决方案: 1.执行 Resources.class.getClassLoader().getResourceAsStream(path) 方法无法获得去字节输入流 解 ...

  2. Linux普通用户使用docker以及docker-compose

    # 添加limstorm普通用户到docker用户组 sudo gpasswd -a limstorm docker # 切换docker用户组,该命令类似login指令,当它是以相同的帐号,另一个群 ...

  3. 帝国cms将没有搜索到结果的关键字存入到数据库的方法

    在帝国cms网站前台搜索一个关键字,如果在网站中查询到了,这个关键字会被记录入搜索关键字表中,但是如果在网站中没有搜索到,就不会记录入搜索关键字表中,那怎么把没有搜索结果的关键字才能记录到数据库中,方 ...

  4. 京东小程序接入ARVR的技术方案和性能调优

    作者:京东零售 戴旭 京东小程序是一个开放技术平台,正在被越来越多的头部品牌选择,用于站内私域流量的营销和运营.诸如各种日化.奢侈品等品牌对ARVR有较多的诉求,希望京东小程序引擎提供一些底层能力,叠 ...

  5. 第2章. reco主题介绍

    1. 这是一个vuepress主题,旨在添加博客所需的分类.TAB墙.分页.评论等能: 2. 主题追求极简,根据 vuepress 的默认主题修改而成,官方的主题配置仍然适用: 3. 你可以打开 [午 ...

  6. vue中实际代码模拟JS中promise调接口的运行流程

    假设我们有一个需要调用接口的场景,我们可以使用Vue中的axios库来发送请求.以下是一个简单的例子: // 引入axios库import axios from 'axios' // 定义一个函数,用 ...

  7. 快速上手Linux核心命令(九):文件备份与压缩

    目录 tar 打包备份 gzip 压缩或解压文件 zip 打包和压缩文件 unzip 解压zip文件 scp 远程文件复制 rsync 文件同步工具 这期呢主要说一说Linux中文件备份与压缩命令,一 ...

  8. YOLO2论文中文版

    文章目录 YOLO9000中文版 摘要 1. 引言 2. 更好 3. 更快 4. 更强 5. 结论 参考文献 YOLO9000中文版 摘要 我们引入了一个先进的实时目标检测系统YOLO9000,可以检 ...

  9. Python 函数传递任意数量的实参

    函数传递任意数量的实参 *形参名,形参名中的星号让python创建了一个空元组,并将收到的所有值都封装到这个元组中 # 案例 *toppings 形参名中的星号让python创建了一个空元组,并将收到 ...

  10. 如何实现一个sync.Once

    sync.Once 是 golang里用来实现单例的同步原语.Once 常常用来初始化单例资源, 或者并发访问只需初始化一次的共享资源,或者在测试的时候初始化一次测试资源. 单例,就是某个资源或者对象 ...