d导入c的示例

原文
在语言中拥有ImportC有个非常酷的好处.使我们能够动态绑定C库,而无需手动编写任何绑定代码!
窍门:
第1步:预处理C库头文件,以便可在D中导入它.
第2步:使用D的编译时内省来生成函数指针和相关的加载程序例程.
第3步:后续动作
第4步:利润!

static import portaudio;

import std.meta;
import std.stdio;
import std.traits;
import core.sys.windows.windows;

struct Tuple(_FuncType, string _Name) {
    alias FuncType = _FuncType;
    enum Name = _Name;
}

//取实际函数的函数指针类型
template FuncType(alias symbol) {
    ReturnType!symbol function(Parameters!symbol) func;
    alias FuncType = SetFunctionAttributes!(typeof(func), functionLinkage!symbol,
        functionAttributes!(typeof(func)));
}

//取模块序列(函数类型,名)
template GetFunctionList(alias Module) {
    alias GetFunctionList = AliasSeq!();
    static foreach (idx, member; __traits(allMembers, Module)) {
        static if (isFunction!(__traits(getMember, Module, member))) {
            GetFunctionList = AliasSeq!(GetFunctionList,
                Tuple!(FuncType!(__traits(getMember, Module, member)), member));
        }
    }
}

//生成模块和加载库的动态绑定
class Dynamic(alias Module, string SharedLib)
{
    //加载动态库
    static HANDLE dll;
    static this() {
        dll = LoadLibraryA(SharedLib);
        !dll && assert(0);
    }

    //声明函数指针
    static foreach (Tup; GetFunctionList!Module) {
        mixin("Tup.FuncType " ~ Tup.Name ~ ";");
    }

    //加载函数指针
    this()
    {
        static foreach (Tup; GetFunctionList!Module) {
            *(cast(void**)&__traits(getMember, this, Tup.Name))
                = cast(void*)GetProcAddress(dll, Tup.Name);
        }
    }
}

void main() {
    // 简单!
    auto dynamic = new Dynamic!(portaudio, "portaudio_x64.dll");
    printf("版本信息%s\n", dynamic.Pa_GetVersionText());
}

好的!我想知道它是否也可以用来生成静态绑定?就像,只是用它来输出有正确函数/结构定义的D模块?
#defines仍然没有帮助
可用

typeof(&__traits(getMember, Module, member))

替换

FuncType!(__traits(getMember, Module, member))

来完全消除FuncType模板.

std.meta/std.traits臃肿而缓慢,我建议坚持使用简单的__traits并复制/粘贴需要的少数(2-3)个函数.
简单的结构就可以了.
static import不好,它会泄漏所有函数到全局范围,一个小技巧:

import pa = portaudio;

(..)

auto dynamic = Dynamic!(pa, "portaudio_x64.dll")();

因此,生成静态绑定可避免大量样板工作,还可得到importC无法完成的完整绑定.
dstep需要libclang,而importC不需要
可用数组生成来替代#defines.
__traits(comment)取注释.

posted @   zjh6  阅读(26)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示