是否可以在内联函数中指定extern?

时间:2015-12-29 04:34:22

标签: d

我有一个函数类型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

1 个答案:

答案 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东西的包装器。