2014-04-03 50 views
6

如何在D中傳遞一個委託給外部函數指針的C函數?將代表傳遞給D中的外部C函數

+1

爲什麼這是downvoted? –

+0

可能因爲你有一個「C」標籤。這裏的C程序員在觸發器上很快......至少那是我的經驗。 – DejanLekic

+0

@OMGtechy我已經嘗試了一些東西,比如簡單地傳遞委託,並試圖使用.funcptr屬性,但它們都沒有工作。我很確定我見過人們這樣做,但我在Google上找不到任何示例。 –

回答

6

讓我交交我在新聞組說:

我如何通過委託來取 函數指針外部C函數?

不能在一般的直接做到這一點,除非你能修改C 功能,那麼你就可以破解它周圍,但委託和 普通函數指針是相當不同的動物。

但也許你可以魔法破解它。注意:

// a C function that needs a plain function 
extern(C) void test(void function() f) { 
    // pretend this is implemented in C 
    f(); 
} 

// just create a random delegate 
void delegate() foo(int a) { 
    return { import std.stdio; writeln(a); }; 
} 

// what we want to work 
void main() { 
    auto dg = foo(10); 
    dg(); // works 

    //test(dg); // won't work 
    test(bindDelegate(dg)); // we want this 
} 

// transform delegate into pointer.. 
import std.traits; 
auto bindDelegate(T, string file = __FILE__, size_t line = __LINE__)(T t) if(isDelegate!T) { 
    static T dg; 

    dg = t; 

    extern(C) 
    static ReturnType!T func(ParameterTypeTuple!T args) { 
      return dg(args); 
    } 

    return &func; 
} 

什麼bindDelegate所做的是創建一個特殊的靜態變量併爲特定呼叫 功能。就好像我們寫了一個單獨的 函數,並且全局地持有它。

__FILE____LINE__東西是骯髒的黑客攻擊,使其 實例化一個單獨的變量+函數對針對不同 線以全局變量保持委託不會那麼容易 覆蓋。

+0

聰明的把戲! :) – DejanLekic

+2

我也剛剛意識到,由於全局持有委託,它將始終分配一個動態閉包,它所指向的內存永遠不會被釋放;該參考文件將繼續存在。 (好吧,你也許可以用同樣的文件和行參數來執行另一個bindDelegate調用,而null可以這樣清除它,但實際上誰會打擾?)這可能是好的和壞的:好的是C可以自信地使用它GC不會過早地清理它。當然,糟糕的是,一旦你完成了它,內存泄漏的可能性就會降低。所以請注意這個警告。 –

+1

如何而不是採取一個文件和行,你拿一個指針的類,並作爲字符串的方法名?這樣它只能被對象或同一位置上的另一個對象覆蓋。 (意味着原始物體無論如何都被毀壞了) –