日韩av无码中文字幕,国产午夜亚洲精品国产成人小说,成人影院午夜男女爽爽爽,欧美 亚洲 中文 国产 综合

首頁 熱點(diǎn) 要聞 國(guó)內(nèi) 產(chǎn)業(yè) 財(cái)經(jīng) 滾動(dòng) 理財(cái) 股票

DLang 與 C 語言交互 天天快看點(diǎn)

2023-06-24 18:33:17 來源 : 博客園

DLang 與 C 語言交互

很難受的是,這部分的文檔太少了,根本沒有 教程向的文章。所以我寫了此文以做分享。

本文原址鏈接(防止機(jī)器搬運(yùn)):https://www.cnblogs.com/jeefy/p/17501476.html

閱讀提示:請(qǐng)保證如下條件:


【資料圖】

會(huì)基本C語言使用,以及其編譯命令。

會(huì)基本D語言使用,以及其編譯命令。

會(huì)使用 Makefile之類的東西(不會(huì)也無所謂),不會(huì)dub

目錄DLang 與 C 語言交互最簡(jiǎn)單的例子鏈接庫函數(shù),參數(shù)?最簡(jiǎn)單的例子
// chello.c#include void hello(void) {    puts("Hello World!");}
// hello.dextern (C) void hello();void main() {    hello();}

其實(shí)上面的兩個(gè)程序的意義非常明顯,就是最基本的 Hello World!輸出罷了。

我們有了上面兩個(gè)文件后可以通過如下命令編譯:

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

最終會(huì)得到一個(gè) main可執(zhí)行文件(也可能是 main.exe,看系統(tǒng))。運(yùn)行它,你就得到了 Hello World!

接下來對(duì)于部分做出解釋。

函數(shù)的聲明:在 hello.d中有一句 extern (C) void hello();,這就是函數(shù)的聲明部分,由于 dlang 與 C++ 一樣在處理函數(shù)名的時(shí)候會(huì)做一些變化,然而 C 中的函數(shù)名卻是不變的,所以需要顯式聲明其函數(shù)名的處理方式:extern (C),也就是按照 C 的處理方式處理,這樣才能調(diào)用到 chello.o中的 hello方法。

編譯的命令:唯一需要注意的是需要把 .o文件顯示的放入編譯命令中。

頭文件:這是困擾我最久的一個(gè)點(diǎn),dlang 如何使用 C 的頭文件?后來才發(fā)現(xiàn)了一個(gè)誤區(qū),dlang 不存在頭文件的說法,也就是說 dlang 無法 直接使用 .h文件。但是我們又需要聲明函數(shù)怎么辦?在官方文檔中有這樣一個(gè)命令:

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

這個(gè)命令的作用在于列出所有聲明的東西(包括函數(shù)與結(jié)構(gòu)體的聲明)。在經(jīng)過一定的修改后,就可以變?yōu)?.d文件(做類似于頭文件的作用)。

接下來我們嘗試一點(diǎn)更加高級(jí)的東西。

鏈接庫

我使用的例子是我自己在寫的一個(gè)小東西。參見:

假如我需要使用一個(gè)簡(jiǎn)單的 SDL程序以顯示一個(gè)色塊。我可以很輕易的寫出如下代碼:

// cshow.c#include #include // 省略了部分宏定義....避免冗長(zhǎng)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;}

對(duì)于 dlang 中的調(diào)用也很明了:

// 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

我們最終會(huì)發(fā)現(xiàn)出現(xiàn) undefined reference to ...的錯(cuò)誤。

在官方文檔中并沒有提及使用系統(tǒng)鏈接庫的問題。但是 隱晦的給出了解決方法。

我們直接找到 libSDL2.so所在的位置。在我的系統(tǒng)中是 /usr/lib/x86_64-linux-gnu/libSDL2.so

于是編譯命令新增一個(gè)部分,變?yōu)椋?/p>

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

也就是直接把鏈接庫也帶上……屬實(shí)給我整無語了。

啊,于是,我們不能真的吧所有庫的位置全部找到,然后在編譯的時(shí)候一個(gè)一個(gè)復(fù)制上去吧。所以就需要類似與 Make或者 CMake, meson之類的構(gòu)建工具輔助我們。這部分不過多展開。

函數(shù),參數(shù)?

有些時(shí)候,我們想要在 C 中使用 dlang 分配的內(nèi)存。如:

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

自然的,我們可以想到:

// example.d// 錯(cuò)誤示例?。。。。。。。。。。。。。。。。。。?!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]);}

可以編譯通過,然后運(yùn)行……輸出 0。

講道理應(yīng)該是輸出 1才對(duì)。

那么很明顯,類型出了問題,我們不應(yīng)該如此操作。

于是參考官方文檔。正確的姿勢(shì)如下:

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 中,可變長(zhǎng)數(shù)組其實(shí)有兩個(gè)變量,可以理解為:

struct {    int length;    int * ptr;}

當(dāng)然,類型肯定不是這樣的……

也就是說 arr.ptr中才存著數(shù)據(jù)。所以如此。

那么考慮不可變長(zhǎng)數(shù)組。好像還是只能使用上面那種聲明和調(diào)用方法……

這就是在傳遞參數(shù)的時(shí)候最需要注意的一個(gè)點(diǎn)。其他的參數(shù)類型轉(zhuǎn)化可以參考:

https://dlang.org/spec/interfaceToC.html

https://wiki.dlang.org/D_binding_for_C

關(guān)鍵詞:
相關(guān)文章

最近更新
黑莓8310刷機(jī)教程 2023-06-24 18:13:14
精彩推送