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位
就得用微软的VC2019
或mingw-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
,林操/bsd
有gcc
包,用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
,d
的showmax1.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
都可以.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现