Dlang 与 C 语言交互(二)
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文件。具体作用请读者自行探究。
还有几个点说一下:
在调用
dlopen和dlclose时,会分别调用的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 语言交互(二)的更多相关文章
- 使用C语言实现二维,三维绘图算法(1)-透视投影
使用C语言实现二维,三维绘图算法(1)-透视投影 ---- 引言---- 每次使用OpenGL或DirectX写三维程序的时候, 都有一种隔靴搔痒的感觉, 对于内部的三维算法的实现不甚了解. 其实想想 ...
- 使用C语言实现二维,三维绘图算法(3)-简单的二维分形
使用C语言实现二维,三维绘图算法(3)-简单的二维分形 ---- 引言---- 每次使用OpenGL或DirectX写三维程序的时候, 都有一种隔靴搔痒的感觉, 对于内部的三维算法的实现不甚了解. 其 ...
- 使用C语言实现二维,三维绘图算法(2)-解析曲面的显示
使用C语言实现二维,三维绘图算法(2)-解析曲面的显示 ---- 引言---- 每次使用OpenGL或DirectX写三维程序的时候, 都有一种隔靴搔痒的感觉, 对于内部的三维算法的实现不甚了解. 其 ...
- Swift语言指南(二)--语言基础之注释和分号
原文:Swift语言指南(二)--语言基础之注释和分号 注释 通过注释向自己的代码中注入不可执行的文本,作为你自己的笔记或提示.Swift编译器运行时会忽略注释. Swift的注释与C语言极其相似,单 ...
- FFI (语言交互接口(Foreign Function Interface))
FFI(Foreign Function Interface)是用来与其它语言交互的接口, 在有些语言里面称为语言绑定(language bindings), Java 里面一般称为 JNI(Java ...
- #r语言(二)笔记
#r语言(二)笔记 #早复习 #概述:R是用于统计分析.绘图的语言和操作环境 #对象: #数据类型--统称为对象 #向量(vector):用于存储数值型.字符型或逻辑型数据的一维数组. #定义向量: ...
- Swift5 语言指南(二十八) 高级运算符
除了Basic Operators中描述的运算符之外,Swift还提供了几个执行更复杂值操作的高级运算符.这些包括C和Objective-C中您熟悉的所有按位和位移运算符. 与C中的算术运算符不同,S ...
- Swift5.1 语言指南(二十九)高级运算符
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- iOS开发之SQLite-C语言接口规范(二) —— Prepared Your SQL Statements
在<SQLite的C语言接口规范(一)>中介绍了如何去连接打开数据库,本篇博客就介绍如何操作数据库,本篇主要给出了如何执行数据库查询语句(Select), 然后遍历结果集.本篇博客就直接使 ...
- 遗传算法的C语言实现(二)-----以求解TSP问题为例
上一次我们使用遗传算法求解了一个较为复杂的多元非线性函数的极值问题,也基本了解了遗传算法的实现基本步骤.这一次,我再以经典的TSP问题为例,更加深入地说明遗传算法中选择.交叉.变异等核心步骤的实现.而 ...
随机推荐
- 一些随笔 No.1
耦合 耦合是一个设计与逻辑上的问题 例如一个软件有20个功能,删除任意一个功能对别的19个功能不造成影响,就是低耦合 如果删除一个功能后其他功能会失去完整性,那么就是高耦合 Difference be ...
- [Linux]VMware启动CENOTS7时报"welcome to emergency mode!"【转载】
1 问题描述 由于通过VMwaer快速克隆了一台CENTOS7.9的虚拟机. 但启动时报如下错误信息 welcome to emergency mode!after logging in ,type ...
- stable diffusion打造自己专属的LORA模型
通过Lora小模型可以控制很多特定场景的内容生成. 但是那些模型是别人训练好的,你肯定很好奇,我也想训练一个自己的专属模型(也叫炼丹-_-). 甚至可以训练一个专属家庭版的模型(family mode ...
- Java设计模式 —— 适配器模式
9 适配器模式 9.1 结构型模式 结构型模式(Structural Pattern) 关注如何将现有类或对象组织在一起形成更强大的结构.结构型模式根据描述目标不同可以分为两种: 类结构型模式:关心类 ...
- mysql数据库的登录脚本
######################## ku脚本: 可以使用以下ku脚本,它可以根据提供的参数登录到MySQL数据库: #!/bin/bash # Check for correct num ...
- Http请求get与post请求方式的各种相关面试总结
转载请注明出处: GET方法和POST方法是两种HTTP请求方法,GET方法通过URL传递参数,可以缓存,但参数长度有限,一般用于获取资源:POST方法通过表单传递参数,不能缓存,参数长度没有限制,一 ...
- 【Azure Developer】使用 Microsoft Graph API 获取 AAD User 操作示例
问题描述 查看官方文档" Get a user " , 产生了一个操作示例的想法,在中国区Azure环境中,演示如何获取AAD User信息. 问题解答 使用Microsoft G ...
- Docker容器核心实践(操作容器)
镜像和容器是docker中最基础的概念,镜像可以理解为包含应用程序以及其相关依赖的一个基础文件系统,在其启动过程中,以只读的方式被用于创建容器的运行环境,本质上是基于UnionFS文件系统的一组镜像层 ...
- P5356 [Ynoi2017] 由乃打扑克
md调了5h才调出来恶心坏了没想到这么快就做了第二道Ynoi 据说这题其实不卡常 屠龙宝刀点击就送 题面也很清楚,给定两种操作,一种是区间加,一种是询问区间内第 k 小的数的值是多少. 对于区间加,在 ...
- AGC061 F Perfect String
毒瘤出题人,史诗加强 AGC 的 F-- 然而我连原题都不会,所以只学了原题做法. 翻译一下题意就是给定一张循环网格图,求经过 \((0,0)\) 的闭合回路条数. 由于网格图中每一个位置都等价,所以 ...