2011-06-21 37 views
4

我正在研究一个现有C库的D绑定,我有一堆函数定义和一堆绑定。例如:在D中混合具有可变数量的字符串参数的混合?

// Functions 
void function(int) funcA; 
long function() funcB; 
bool function(bool) funcC; 
char function(string) funcD; 
// etc... 

// Bindings 
if(!presentInLibrary("func")) return false; 
if(!bindFunction(funcA, "funcA")) return false; 
if(!bindFunction(funcB, "funcB")) return false; 
if(!bindFunction(funcC, "funcC")) return false; 
if(!bindFunction(funcD, "funcD")) return false; 
// etc... 

该模型与Derelict如何处理OpenGL扩展加载非常相似。但是,这看起来像是很多多余的输入。我真的很想要一种方式来表达上面的“绑定”部分,如下所示:

BINDGROUP("func", "funcA", "funcB", "funcC", "funcD", ...); // Name of function group, then variable list of function names. 

这是可以使用mixins完成的事情吗?

回答

5

我用这个当我正做动态加载,虽然它没有回答你的问题,你可能能够适应它:

void function() a; 
int function(int) b; 
void function(string) c; 

string bindFunctions(string[] funcs...) 
{ 
    string ret; 
    foreach (func; funcs) 
    { 
     ret ~= func ~ ` = cast(typeof(` ~ func ~ `))lib.getSymbol("` ~ func ~ `");`; 
    } 
    return ret; 
} 
mixin(bindFunctions("a", "b", "c")); 

这里bindFunctions("a", "b", "c")返回一个字符串,看起来像:

a = cast(typeof(a))lib.getSymbol("a"); 
b = cast(typeof(b))lib.getSymbol("b"); 
c = cast(typeof(c))lib.getSymbol("c"); 

lib.getSymbol()返回从dl_open()指针等希望这有助于。

+0

我不得不嘲笑它,但我认为你应该可以在不使用字符串混合的情况下使用静态foreach机能的研究。您可能需要使用模板混合来从正确的作用域绑定事物。 – BCS

4

我假设你的意思是string mixins?你可以只作简单直接的使用D的可变参数的语法:

string BINDGROUP(string functionGroup, string[] functions...) 
{ 
    // ... 
} 

mixin(BINDGROUP("func", "funcA", "funcB", "funcC", "funcD")); 
+0

我的印象是,这是行不通的,因为字符串必须在编译时被知道,并且有一个字符串变量可以打破这种情况。如果情况并非如此,我肯定会这样做! (另外,是的,我的意思是string mixins,谢谢你的澄清)。 –

+0

@标记编译器将尝试在编译时计算弱纯函数,如果结果需要完成编译(使用'enum'或'mixin')并在无法计算时抛出错误。除了可变参数(以及一般的模板参数)在实例化时在编译时被扩展 –

4

我相信这是你在找什么

template BINDGROUP(string group,T...){ 
    alias BINDGROUP presentInLibrary("func") && BINDGROUPFUNCS!(T); 
} 

template BINDGROUPFUNCS(T...){ 
    static if(T.length)alias BINDGROUPFUNCS true; // all is successful 
    else alias BINDGROUPFUNCS bindFunction(mixin(T), T) && BINDGROUPFuncts!(T[1..$]); 
} 

我在这里使用递归模板声明,你也可以做这与foreach循环