• 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 。也就是说,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

  • 相关阅读:
    IO拷贝文件大全
    Scalable Zero-shot Entity Linking with Dense Entity Retrieval
    2022-09-02 mysql-in函数官方说明记录
    STM8的C语言编程(3)+――+GPIO输出和输入
    Miller_Rabbin算法判断大素数
    c++语言基础概述
    计算机毕业设计(附源码)python智能超市导购系统
    java95-线程的优先级
    一分钟安装NinJa教程(Ubuntu Linux系统)
    SpringBoot自动装配详解_回顾一下2
  • 原文地址:https://www.cnblogs.com/jeefy/p/17503853.html