使用平台呼叫
p/invoke,它的全名叫平台呼叫(platform invoke),用於呼叫dll 中實現的非託管的單調(flat)程式設計介面,被稱為使用c或c++ 呼叫約定(calling conventions)。最有名的例子是win32 程式設計介面,這是乙個巨大的庫,它公開了windows 所有的內建功能。
為了呼叫單調的非託管程式設計介面,必須首先定義準備呼叫的函式,可以分成兩步:第一步,用system.runtime.interopservices 命名空間下的 dllimport 特性(attribute),能夠定義包含想匯入函式的 .dll,加上一些其他的可選特性;第二步,用關鍵字extern,加以 c 風格函式呼叫的簽名,這樣,指定了返回型別為f# 型別,和函式的名字,最後是用括號括起來的引數型別和引數名。結果這個函式就能像外部的.net 方法一樣進行呼叫。
下面的例子演示了如何匯入windows 函式messagebeep,並呼叫:
open system.runtime.interopservices
// declare a function found in an external dll
["user32.dll")>]
extern
boolmessagebeep(uint32 beeptype)
// call this method ignoring the result
messagebeep(0ul) |> ignore
注意使用平台呼叫,最棘手的問題就是要找出要呼叫函式的簽名。在 **上有 c# 和 vb .net 中常用程式設計介面的簽名的清單,f# 中需要的簽名也相類似。這個站點是乙個維基百科(wiki),因此可以自由新增 f# 簽名。
下面的**演示了如何使用平台呼叫,目標函式期望乙個指標,有關設定指標需要注意幾點。當定義函式時,需要在型別名字的後面加星號(*),表示傳遞指標;在函式呼叫之前,還要定義乙個可變識別符號,表示指標指向的記憶體區域,它可能不是全域性的,但是在頂層,必須是函式定義的一部分。這就是為什麼定義函式main,識別符號status 是函式定義的一部分;最後,必須使用位址運算子(&&),保證傳遞給函式的是指標而不是值本身。
提示編譯這段**總是有警告,因為使用了位址運算子(&&)。要抑制這個警告,可以使用編譯器開關--nowarn 51,或者命令#nowarn 51。
opensystem.runtime.interopservices
// declare a function found in an external dll
["advapi32.dll")>]
extern boolfileencryptionstatus(string filename, uint32* status)
let main() =
//declare a mutable idenifier to be passed to the function
letmutable status = 0ul
// call thefunction, using the address of operator with the
// secondparameter
fileencryptionstatus(@"c:\test.txt", && status) |>ignore
printfn"%d" status
main()
這個例子的執行結果如下(假設在 c: 盤根目錄下有乙個檔案test.txt,加過密的):
1ul注意
平台呼叫也可以執行在 mono 平台上,語法與 f# 中的完全一樣,而難點在於保證要呼叫的庫在所有的目標平台上都可用,且遵循在所有不同的平台上庫的不同的命名約定。更多有關解釋的細節,請看上的文章。
dllimport 特性有一些有用的函式,能夠設定用來控制如何呼叫非託管的函式。表 14-1 做了彙總。
表 14-1 dllimport 上有用的特性
特性名描述charset
定義了傳送字串資料的字符集,可以是 charset.auto、charset.ansi、charset.unicode
entrypoint
設定呼叫函式的名字。如果沒有給定名字,那麼,關鍵字 extern 後面的名字就作為預設定義的函式名。
setlasterror
這是乙個邏輯值,指定是否遇到任何錯誤都應該傳送,因此,通過呼叫 marshell.getlastwin32error() 方法檢查可用性。
注意因為有 com 元件,沒有等價的.net 的非託管程式設計介面的數量在持續減少,因此,在準備呼叫函式前檢查一下是否有等價的託管函式,通常會節省大量時間。
平台呼叫P INVOKE 一 基礎篇
平台呼叫技術 p invoke 主要用於處理在託管 中呼叫c c 庫函式及win32 api函式等非託管函式的情形 一 基本要素 乙個簡單例子 c 宣告 extern c declspec dllexport int multiply int factora,int factorb 實現 int m...
C 高階與初心 (二)P Invoke平台呼叫
最近某個專案要採集交易終端的資訊用於監管,主要廠商給出了api,c 版的。開啟hard模式!c 呼叫c 的dll基本就兩種方法 加乙個vc 專案包一層,或者使用p invoke 平台呼叫 前者對於純c 的客戶端來說,增加了複雜性。那就只剩下平台呼叫了。使用平台呼叫的過程比較艱辛,主要遇到了兩個問題 ...
奇異的Pinvoke呼叫
我們的乙個c 專案需要呼叫c 的dll,通過pinvoke進行方法呼叫。其中的乙個方法及其引數的定義是這樣的 structlayoutattribute layoutkind sequential public struct xvid gbl info t dllimportattribute xv...