d同c对接入门

原地址
早期的d的一个设计目标就是与c对接.详细参考,因此,提供abi兼容,允许访问c标准库,并利用与c/c++编译器相同的目标文件格式/链接器.大多数d类型,甚至直接与c构兼容,并可自由传递给c函数.当然得加上外(c).很多时候,你可以复制/粘贴c代码,然后稍微修改下,就可以编译了.同样,用c声明的也可从c端调用d.
但,d去掉了c的缺点.用数组边界检查/编译时检查内存安全来消除c的缺点.同时消除c最大错误,混合了指针/数组.在这里有些基础
本系列,关注很容易忽略的地方,基础的可以结合官方文档(注,官方文档是个宝库)看上段.
代码,由读者来编译/链接,有对有错,理解编译器错误很重要.
c代码在窗口上用cl/dmc,其他平台上用gcc/clang.d则用dmd.窗口c编译器细节
举个在绑定c时可能发生的例子:
将展示c源码,并编译成供d链接的目标代码.先讲窗口,再讲其他平台,命令都差不多.
在同一目录,保存以下c/d代码.名字要区分,不然会覆盖.

#include <stdio.h>
void say_hello(void) 
{
    puts("Hello from C!");
}

上面是chello.c,下面是hello.d:

extern(C) void say_hello();
void main() 
{
    say_hello();
}

外(c)是个链接属性.表示按c来链接,即不混杂.
窗口直接在这里下载.点安装就一路行了.同外部目标文件链接时,关键是格式/架构(操作系统)要对.也可用dmc(在此下载)来编译c.其输出omf格式.然后,可以:

dmc -c chello.c
dmd hello.d chello.obj
hello

-c只编译.64位就得用微软的VC2019mingw-64编译c.

cl /c chello.c
dmd -m64 hello.d chello.obj
hello

32位命令如下:

cl /c hello.c
dmd -m32mscoff hello.c chello.obj
hello

dmd-m32表明是32位,但仍然输出omf格式.可用-m32mscoff开关来生成匹配微软的coff格式.
其他平台一般是gcc/clang.马操可用XCode商店安装clang,林操/bsdgcc包,用apt-get install build-essential等,德编等,参考文档.
CC编译器命令,用gcc/clang替换.

CC -c chello.c
dmd hello.d chello.o
./hello

如果你在64位系统,安装了32位工具,你可以用-m32来生成32位工具.
现在来看陷阱,d的特征是所有平台类型的大小是固定的.2字节,4字节.永远不变.这与c不同.c大小的规范不细致,由实现决定.当然目前现代编译器有共同约定.但不包括长/正长.
d长/正长始终是8字节.不变.在version(Posix)下的64位系统也是8字节.但在32位系统下,为4字节,在窗口下,32/64位的长/正长均为4字节.
现在,c99一般在stdint.h中用int32_t/int64_t来消歧.但仍可能遇见c库.
考虑如下c函数:

#include <limits.h>
unsigned long max_val(void)
{
    return ULONG_MAX;
}

maxval.c,dshowmax1.d实现如下:

extern(C) ulong max_val();
void main()
{
    import std.stdio : writeln;
    writeln(max_val());
}

这依赖于c编译器和架构,如dmc/cl(32/64)上都表现不一样.答案分别为:7316910580432895,59663353508790271,4294967295.这里正长c都为32位,最后1个是对的,我猜是x64存储在RAX中,所以可以读进d正长.重点是x86下两个值是垃圾,因为d端期望从32位寄存器中返回64位值.读了超过给出的值.
d运行时在core.stdc.config中,给出了c版本的长/正长(c_long/c_ulong).这两个匹配编译时c运行时实现和架构配置.然后,只需修改下声明.

import core.stdc.config : c_ulong;
extern(C) c_ulong max_val();
void main()
{
    import std.stdio : writeln;
    writeln(max_val());
}

showmax2.d.编译并运行.然后就对了.还在core.stdc.config中定义了c_long_double,来匹配long double来绑定c库.除了-m32mscoff这个开关,可以直接用ldc/gdc都可以.

posted @   zjh6  阅读(28)  评论(0编辑  收藏  举报  
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示