​原文​​​ 在语言中拥有​​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)​​取注释.