首页 > 创新 >

DLang 与 C 语言交互-天天报道

2023-06-24 17:10:15 来源:博客园

DLang 与 C 语言交互

很难受的是,这部分的文档太少了,根本没有 教程向的文章。所以我写了此文以做分享。

本文原址链接(防止机器搬运):https://www.cnblogs.com/jeefy/p/17499441.html


【资料图】

阅读提示:请保证如下条件:

目录

最简单的例子

// chello.c#include void hello(void) {    puts("Hello World!");}
// hello.dextern (C) void hello();void main() {    hello();}

其实上面的两个程序的意义非常明显,就是最基本的 Hello World!输出罢了。

我们有了上面两个文件后可以通过如下命令编译:

gcc -c chello.cdmd hello.d chello.o

最终会得到一个 main可执行文件(也可能是 main.exe,看系统)。运行它,你就得到了 Hello World!

接下来对于部分做出解释。

  1. 函数的声明:在 hello.d中有一句 extern (C) void hello();,这就是函数的声明部分,由于 dlang 与 C++ 一样在处理函数名的时候会做一些变化,然而 C 中的函数名却是不变的,所以需要显式声明其函数名的处理方式:extern (C),也就是按照 C 的处理方式处理,这样才能调用到 chello.o中的 hello方法。

  2. 编译的命令:唯一需要注意的是需要把 .o文件显示的放入编译命令中。

  3. 头文件:这是困扰我最久的一个点,dlang 如何使用 C 的头文件?后来才发现了一个误区,dlang 不存在头文件的说法,也就是说 dlang 无法 直接使用 .h文件。但是我们又需要声明函数怎么办?在官方文档中有这样一个命令:

    gcc -E -P program.h > program.lst

    这个命令的作用在于列出所有声明的东西(包括函数与结构体的声明)。在经过一定的修改后,就可以变为 .d文件(做类似于头文件的作用)。

接下来我们尝试一点更加高级的东西。

链接库

我使用的例子是我自己在写的一个小东西。参见:

假如我需要使用一个简单的 SDL程序以显示一个色块。我可以很轻易的写出如下代码:

// cshow.c#include #include // 省略了部分宏定义....避免冗长int showColor(int R, int G, int B) {    SDL_PREWORK(50, 50);    while (!done) {        SDL_MYEQUIT(60);        if (SDL_SetRenderDrawColor(ren, R, G, B, 255) < 0) {            fprintf(stderr, "Error Set render draw color: %s\n", SDL_GetError());            return -1;        }        SDL_RenderFillRect(ren, NULL);        SDL_RenderPresent(ren);    }    SDL_CLEANUP;    return 0;}

对于 dlang 中的调用也很明了:

// color.d// show the color by SDL (written in C)extern (C) int showColor(int, int, int);

只是问题出在编译的部分。

如果我们按照一下步骤编译:

gcc -c cshow.c `pkg-config sdl2 --cflags --libs`dmd color.d cshow.o

我们最终会发现出现 undefined reference to ...的错误。

在官方文档中并没有提及使用系统链接库的问题。但是 隐晦的给出了解决方法。

我们直接找到 libSDL2.so所在的位置。在我的系统中是 /usr/lib/x86_64-linux-gnu/libSDL2.so

于是编译命令新增一个部分,变为:

gcc -c cshow.c `pkg-config sdl2 --cflags --libs`dmd color.d cshow.o /usr/lib/x86_64-linux-gnu/libSDL2.so

也就是直接把链接库也带上……属实给我整无语了。

啊,于是,我们不能真的吧所有库的位置全部找到,然后在编译的时候一个一个复制上去吧。所以就需要类似与 Make或者 CMake, meson之类的构建工具辅助我们。这部分不过多展开。

函数,参数?

有些时候,我们想要在 C 中使用 dlang 分配的内存。如:

// exmaple.cvoid fillMem(int *dst, int size, int val) {    for (int i = 0; i < size; ++i)        dst[i] = val;}

自然的,我们可以想到:

// example.d// 错误示例!!!!!!!!!!!!!!!!!!!!import std.stdio;extern (C) void fillMem(int[] dst, int size, int val);void main() {    int[] arr = new int[](3);    fillMem(arr, 3, 1);    writeln(arr[2]);}

可以编译通过,然后运行……输出 0

讲道理应该是输出 1才对。

那么很明显,类型出了问题,我们不应该如此操作。

于是参考官方文档。正确的姿势如下:

import std.stdio;extern (C) void fillMem(int* dst, int size, int val);void main() {    int[] arr = new int[](3);    fillMem(arr.ptr, 3, 1);    writeln(arr[0]);    writeln(arr[1]);    writeln(arr[2]);    writeln(arr.length);}

为什么如此?在 dlang 中,可变长数组其实有两个变量,可以理解为:

struct {    int length;    int * ptr;}

当然,类型肯定不是这样的……

也就是说 arr.ptr中才存着数据。所以如此。

那么考虑不可变长数组。好像还是只能使用上面那种声明和调用方法……

这就是在传递参数的时候最需要注意的一个点。其他的参数类型转化可以参考:

上一篇:

焦点观察:俄罗斯总统普京发表电视讲话 全球滚动

下一篇:

最后一页

x
推荐阅读

DLang 与 C 语言交互-天天报道

北京首现40℃“三连击”!本轮高温“烤验”何时结束? 天天即时看

焦点观察:俄罗斯总统普京发表电视讲话 全球滚动

特斯拉新 Model 3 内饰曝光:加入线控转向,扬声器、座椅也有升级

滚动:明天开始!海口发布中考期间交通出行提示

北方超40℃面积已达10万平方公里 多地日最高气温突破历史极值-今头条

俄罗斯总统普京将发表讲话|环球看点

国民好车也应该是一辆解决用户痛点的车

均价40元+的贵价咖啡,靠什么“赢过”9.9元的瑞幸?

全球即时:012、不高兴+小剧场

加拿大移民|重磅!加拿大人口突破4000万,全靠移民!|每日信息

世界聚焦:烟台市福山区芝阳山学校开展“剪纸 拓印”主题艺术活动

当前焦点!香港机场一国泰航空客机中止起飞 机上乘客被紧急疏散

微信运营教程_微信运营技巧

神圣之火(关于神圣之火介绍)

电讯报:热刺有意尤文后卫布雷默,并持续关注马奎尔 天天快资讯

有理式概念_什么是有理式_详细一点

世界快看:柱下条形基础_关于柱下条形基础概略

石家庄经济职业学院开设专业有什么 石家庄经济职业学院优势专业是什么

当前快报:百度贴吧怎么增加人气_如何提高论坛人气

浙江省商务厅:全省11市行动 宁波、嘉兴已派出团组

天天快消息!新浪姓名测试打分 姓名测试打分星座网

三消息:姆巴佩将加盟皇马,拜仁2000万签约悍将堪称捡到宝,B席接受沙特报价 世界速看

北京汤河口41.8℃高温冲上全国第一 北京为何会有高温天气 每日速讯

未经许可禁止前往可可西里(未经备案禁止前往可可西里)|世界滚动

乌木卡萨港口英文_乌木怎么鉴别

银川烧烤店爆炸事故,首笔赔付款已到位!|最新消息

氟西汀什么意思备注 氟西汀什么意思

当前关注:美媒:基辅反攻未带来突破

天天播报:美记:勇士和绿军有过关于普尔交易的对话 马刺对普尔也很感兴趣

突发!液化气爆炸致门面坍塌!4人被埋,2人重伤

当前讯息:天天爱消除最新关卡_天天爱消除高分攻略天天爱消除怎么玩

申论王泓滔的课好在哪里 公考路上,你需要的不仅是勇气

世界快播:阿尔巴尼亚足球大中锋是谁

536支队伍!2023年“创客广东”珠海地市赛将开赛

前沿热点:尉犁:“粽”想“尉”见你 第十届罗布人民俗烧烤节火热开幕

奥迪真“掀桌子”了!A4L最大降幅7.8万,还盯着宝马3系?

pps怎么下载电影到电脑(pps怎么下载电影)_观速讯

郑州市首届掼蛋(掼牌)公开赛启幕

陕西一男子花19万元和女主播发生关系,警方:19万元账款全部没收-全球热文

【时快讯】帆船爱好者看过来!不出北京这里一样可实现扬帆碧浪

日本核心CPI连续21个月同比上升

澳大利亚时差_澳大利亚和中国的时差是多少

焦点消息!今年夏天,极端高温是否会成为常态?

中国电信怎么开通港澳漫游(中国电信ipv6怎么开通)

全球新资讯:不顾医生劝阻,每天2包烟,顿顿8两白酒的演员李琦,如今变成这样_全球热门

每日快看:1991年属什么生肖属相_1991年属相

社旗县:艾草丰收季 助农产业兴

热讯:细菌培养的常用方法_细菌培养的方法有哪些

《疯狂爆梗王》莽村拆迁办过关方法推荐