使用 C++ Interop (隱含 PInvoke)
不同於其他 .NET 語言,Visual C++具有互操作性支援,可讓 Managed 和 Unmanaged 程式代碼存在於相同的應用程式中,甚至是在同一個檔案中(使用 Managed、Unmanaged pragmas)。 這可讓 Visual C++開發人員將 .NET 功能整合到現有的 Visual C++ 應用程式中,而不會干擾應用程式的其餘部分。
您也可以從 Managed 編譯呼叫 Unmanaged 函式,並使用 dllexport、dllimport。
當您不需要指定函式參數的封送處理方式,或明確呼叫 DllImportAttribute 時可指定的任何其他詳細數據時,隱含 PInvoke 很有用。
Visual C++提供兩種方式,讓 Managed 和 Unmanaged 函式互通:
.NET Framework 支持明確 PInvoke,而且適用於大部分的 .NET 語言。 但正如其名稱所暗示,C++ Interop 是 Visual C++ 特有的。
C++ Interop
C++ Interop 提供更好的類型安全性,而且實作通常較不乏味。 不過,如果 Unmanaged 原始程式碼無法使用或跨平台專案,C++ Interop 不是選項。
C++ COM Interop
Visual C++支援的互操作性功能,在與 COM元件互通時,會比其他 .NET 語言提供特殊優勢。 C++ Interop 可讓 COM 元件隨時存取,而不是受限於 .NET Framework Tlbimp.exe (類型連結庫匯入工具)的限制,例如對數據類型的有限支援和每個 COM 介面的每個成員的強制公開。C++ Interop 允許存取 COM 元件,而且不需要個別的 Interop 元件。 不同於 Visual Basic 和 C#,Visual C++可以直接使用一般 COM 機制來使用 COM 物件(例如 CoCreateInstance 和 QueryInterface)。 這可能是因為C++ Interop 功能,導致編譯程式自動插入轉換程序代碼,以從 Managed 移至 Unmanaged 函式,然後再返回一次。
使用 C++ Interop 時,可以使用 COM 元件,因為它們通常使用,或者可以包裝在C++類別內。 這些包裝函式類別稱為自定義運行時間可呼叫包裝函式或CRCW,而且在應用程式程式代碼中直接使用 COM 有兩個優點:
產生的類別可以從 Visual C++ 以外的語言使用。
COM 介面的詳細數據可以從Managed用戶端程式代碼隱藏。 .NET 數據類型可用來取代原生類型,而且數據封送處理的詳細數據可以在 CRCW 內以透明方式執行。
不論 COM 是直接使用還是透過 CRCW 使用,都必須封送處理簡單、blittable 類型的自變數類型。
Blittable 類型
針對使用簡單、內建類型的 Unmanaged API(請參閱 Blittable 和非 Blittable 類型),不需要特殊編碼,因為這些數據類型在記憶體中具有相同表示法,但更複雜的數據類型需要明確的數據封送處理。 如需範例,請參閱 如何:使用 PInvoke 從 Managed 程式代碼呼叫原生 DLL。
範例
// vcmcppv2_impl_dllimp.cpp
// compile with: /clr:pure user32.lib
using namespace System::Runtime::InteropServices;
// Implicit DLLImport specifying calling convention
extern "C" int __stdcall MessageBeep(int);
// explicit DLLImport needed here to use P/Invoke marshalling because
// System::String ^ is not the type of the first parameter to printf
[DllImport("msvcrt.dll", EntryPoint = "printf", CallingConvention = CallingConvention::Cdecl, CharSet = CharSet::Ansi)]
// or just
// [DllImport("msvcrt.dll")]
int printf(System::String ^, ...);
int main() {
// (string literals are System::String by default)
printf("Begin beep\n");
MessageBeep(100000);
printf("Done\n");
}
Begin beep
Done
本節內容
如需在 Interop 案例中使用委派的資訊,請參閱委派(C++元件延伸模組)。