2016-12-19 26 views
7

我正在爲現有庫(用C語言編寫)編寫一個FFI接口。Squeak中的FFI:Singleton ExternalLibrary與ExternalStructures中的類方法與方法?

該庫使用了大量的不透明結構,因此我定義了幾個ExternalStructures(沒有字段)用作void*

現在,我已經看到了與庫接口的兩種方式(或四個):

有每個導出函數的方法的ExternalLibrary:這可能會在實例類的方法,然後用單身模式有一個單一的實例。或實現與「更加複雜」語法包括在FFI編譯的moduleName像在類側的方法:

ffiTestFloats: f1 with: f2 
    "FFITestLibrary ffiTestFloats: $A with: 65.0" 
    <cdecl: float 'ffiTestFloats' (float float) module:'SqueakFFIPrims'> 
    ^self externalCallFailed 

有什麼好?

此外,我已經看到了其他方式做到這一點,根本沒有ExternalLibrary,並直接在ExternalStructure執行方法。我更喜歡這個第二部分,但是,所有的FFI接口定義都通過幾個類傳播,並且維護和移植到其他平臺,Smalltalk方言或庫版本可能更復雜。

那麼,做這件事的「正確」方式是什麼?

+0

我不知道哪個是Squeak的方式,但我喜歡每個導出函數使用一個方法的ExternalLibrary方法。在ExternalStructure中使用這些方法可能會很棘手,因爲可能有幾個結構或者根本沒有一個用於某些功能。 –

回答

1

我會堅持傳統的建模方法。我們在這裏有一個外部庫,然後讓我們爲它創建一個類並在其對象中複製它的API,當然,使用執行所需FFI調用的實例端方法。

我們已經使用這種方法已有二十年了,經驗表明單例模式在這種情況下工作得非常好,因爲它使客戶的生活變得輕鬆。當然,這個工具必須小心處理,所以你不要在不適當的地方引用這個庫實例。但是請注意,這不是一個重要的決定,但是您必須以某種方式將庫的唯一實例保存在某處。

在所涉及的外部結構中實現FFI調用並不自然,因爲某些調用可能涉及多個結構或根本不涉及。那麼,你會把這些放在哪裏?

你還提到了在課堂上實施方法的想法。畢竟,我們都同意每個圖書館應該只有一個實例,不是嗎?拋棄這種可能性的一個原因是,類方法會提供不太靈活的實現。爲什麼?因爲有一件事是使用一些機制只有一個類的實例,另一個是使它不可能擁有它。如果你的對象是一個實例(而不是一個類),你仍然可以避免明確鼓勵對單個實例的限制,並能夠創建另一個實例。這會違反你自己的規則,但能夠這樣做總是更好。想要做到這一點的一個簡單情況就是測試。您可以創建另一個連接的實例,以表示該庫的另一個版本,並且無需修改該類就可以對其進行測試。不選擇類方法的另一個原因更爲微妙:類代表事物的概念,而不是事物。因此,它們的自然協議與其實例的協議不同。將兩個接口分開將爲您的設計增加清晰度。

+0

格拉只是問在哪裏放置函數聲明 - 據我所知他不想/需要在結構內窺視。 –

+0

@BertFreudenberg好點。我刪除了不相關的段落,並添加了幾條堅持這個問題的評論。謝謝! –

1

我更喜歡第一個選項,一個代表C函數和實例方法之間一對一映射的外部庫的對象。當然,這是抽象層次較低,在它之上應該建立更好的抽象。 我不會使用「單身人士」,我認爲沒有必要爲「一類的一個實例」。你需要的是一個知名的對象,並且該對象不應該從內部直接引用以避免耦合,它應該在需要時作爲參數傳遞。

3

我會採用ExternalLibrary的方法,因爲它可以讓您自定義庫名稱,而不是在每種方法中對其進行硬編碼。