首页 > 其他分享 >DLang 与 C 语言交互

DLang 与 C 语言交互

时间:2023-06-24 17:23:47浏览次数:42  
标签:arr DLang int void dlang SDL 交互 hello 语言

DLang 与 C 语言交互

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

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

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

  • 会基本C语言使用,以及其编译命令。

  • 会基本D语言使用,以及其编译命令。

  • 会使用 Makefile 之类的东西(不会也无所谓),不会 dub

目录

最简单的例子

// chello.c
#include <stdio.h>

void hello(void) {
    puts("Hello World!");
}
// hello.d
extern (C) void hello();

void main() {
    hello();
}

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

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

gcc -c chello.c
dmd 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 <stdio.h>

#include <SDL2/SDL.h>

// 省略了部分宏定义....避免冗长

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.c
void 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 中才存着数据。所以如此。

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

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

标签:arr,DLang,int,void,dlang,SDL,交互,hello,语言
From: https://www.cnblogs.com/jeefy/p/17499441.html

相关文章

  • c语言-字符串+转义字符+注释、语句、函数、数组、操作符 2
    一、字符串+转义字符+注释字符串类型(相较于字符数据类型):eg:“”;//空字符串定义:由双引号引起的一串字符为字符串字面值,简称字符串。(后面默认会有\0,结束标志不算内容intmain(){chararr1[]="abc";//数组//"abc"——'a''b''c''\0'——'\0'......
  • 初始C语言2
    学习感想今天一大早起来就开始看(肝)鹏哥的视频,三个小时半啊!!!从早上8点多到现在快13点,知道这三小时半我怎么过的吗?呜呜呜呜!但是终于坚持学完了这一个视频。这一次视频还是讲的很基础的内容,之前自己也涉及过,但也学到了不一样的东西,比如讲到常量时,不仅提到了我之前学过的常变量和定义标......
  • C语言 【阶乘】
    原#include<stdio.h>intmain(){intn;intsum=1;printf("输入数字:");scanf("%d",&n);for(inti=1;i<=n;i++){sum*=i;}printf("%d的阶乘为%d\n",n,sum);return0;......
  • C语言I/O操作
    (只写了文件调用的,C库自己看吧)1、系统调用定义:指操作系统提供给用户程序的调用的一组“特殊接口”,用户程序可以通过这组特殊接口来获得操作系统内核提供的服务2、Linux文件描述符当某个程序打开程序时,操作系统会返回相应的文件描述符,(相当于文件的别名,打开之后就只用......
  • qt---多语言支持
    qt---多语言支持keywords:翻译多语言可以翻译的有2种:界面上的,默认都是会翻译的,如果不想翻译,可以取消勾选相应的"可翻译的"代码中出现的文本,如果需要翻译,可以用tr包裹,如:tr("hello")准备好之后,工具->外部->Qt语言家->更新翻译,这样就可以在相应的ts文件中生成待翻译......
  • LLE算法在自然语言生成中的应用:实现文本到语音的情感迁移
    目录自然语言生成(NaturalLanguageGeneration,NLP)是人工智能领域的一个分支,它利用大量的文本数据训练出语言模型,从而实现对自然语言的生成和理解。在NLP中,情感迁移(EmotionTransfer)是一个重要的任务,它可以通过对已有文本的情感分析,将其转化为语音,从而实现文本到语音的情感迁......
  • C语言【三数中找最大值】
    原#include<stdio.h>intmain(){inta,b,c;printf("输入三个数:");scanf("%d%d%d",&a,&b,&c);if(a>b&&a>c){printf("最大值为:%d\n",a);}elseif(a>b......
  • 自然语言处理中数据增强(Data Augmentation)技术最全盘点
    与“计算机视觉”中使用图像数据增强的标准做法不同,在NLP中,文本数据的增强非常少见。这是因为对图像的琐碎操作(例如将图像旋转几度或将其转换为灰度)不会改变其语义。语义上不变的转换的存在是使增强成为ComputerVision研究中必不可少的工具的原因。是否有尝试为NLP开发增强技......
  • 中文医疗领域自然语言处理相关数据集、经典论文资源蒸馏分享
        在医疗领域,一些应用已经从科幻小说变为现实。人工智能系统通过了中国和英国的医学执照考试,而且它们比普通医生考得更好。最新的系统比初级医生能更好地诊断出55种儿科疾病。但是,这些系统比第一批计算机视觉深度学习应用(例如研究一个图像)中的一些更难构建,因为它们需要具有......
  • 自然语言处理顶会ACL 2020会议核心要点分享
        今年受疫情影响,ACL只能举行线上虚拟会议,因此不能近距离跟行业学者们进行交流。但我任然想把我了解到的ACL的争取趋势和研究动态分享处理,因而有了这篇文章。     这些年来ACL的总体趋势    在开始讨论整个趋势之前之前,让我们先看一下ACL会议的一些总体统计数据。今......