我有一个函数类型alias Func = extern (C) void function();
和一个接收Func作为参数extern (C) void whatever(Func);
的函数。在调用whatever
时是否可以使用extern(C)链接创建内联函数?
例如:
Func x = function() {}
whatever(x); //Works
whatever(function() {}); // Compilation error, invalid linkage
答案 0 :(得分:2)
是......但仅当Func
接受参数并且您使用 out 定义内联函数时才指定该参数的类型。
extern(C) alias Func = void function(int);
extern(C)
void foo(Func f) {
}
void main() {
Func x = function(a) {};
pragma(msg, typeof(x));
foo(x);
foo(function(a) {});
}
有效。我没有尝试过,在dlang.org查看语法,它并没有说它允许内联函数上的extern
字,所以我不认为我错过任何东西(尽管它我总是有可能。)
参数之所以有效,是因为当你没有在函数文字中指定一个参数类型时,编译器会将它作为模板文字,自动实例化为接收函数所期望的类型。你传了它。
由于接收函数需要extern(C)
,模板也可以免费获得。
请注意,我没有尝试运行这个,也许它可以编译但在运行时做错了。
但是,我不相信零参数内联函数有任何类似的技巧。
你可能还可以编写一个包装你给定函数的全局级模板并返回它。看哪:
extern(C) alias Func = void function();
extern(C)
void foo(Func f) {
}
template wrap(alias f) {
extern(C) void wrapped() {
// you can also put stuff like try/catch
// in here if you like so exceptions don't
// accidentally pass through the C function
return f();
}
Func wrap() {
return &wrapped;
}
}
void main() {
Func x = function() {};
pragma(msg, typeof(x));
foo(x);
foo(wrap!(function() {}));
}
包装器解决方案也有优点和缺点,比如能够添加try / catch或在普通D函数上使用,但是你需要实际使用包装器并编写它(尽管你可以自动编写使用std.traits东西的包装器。