Terjemahan tanda tangan metode implisit dalam interop .NET
Agar tetap agnostik bahasa pemrograman, sistem WINDOWS COM dan banyak API Windows mengembalikan jenis bilangan bulat 4 byte yang HRESULT
disebut untuk menunjukkan apakah API berhasil atau gagal, bersama dengan beberapa informasi tentang kegagalan tersebut. Nilai lain yang perlu diteruskan ke pemanggil adalah "dikembalikan" melalui parameter penunjuk yang bertindak sebagai parameter "keluar", dan biasanya merupakan parameter terakhir dalam tanda tangan. Bahasa seperti C# dan Visual Basic secara tradisional menerjemahkan kode kegagalan ke pengecualian untuk mencocokkan bagaimana kegagalan biasanya disebarluaskan dalam bahasa, dan mengharapkan tanda tangan metode interop tidak menyertakan HRESULT
. Untuk menerjemahkan tanda tangan metode ke tanda tangan asli, runtime memindahkan nilai pengembalian metode ke parameter "keluar" tambahan dengan satu tingkat tidak langsung lagi (dengan kata lain, menjadikannya penunjuk ke jenis pengembalian tanda tangan terkelola), dan mengasumsikan nilai pengembalian HRESULT
. Jika metode terkelola mengembalikan void
, tidak ada parameter tambahan yang ditambahkan dan nilai yang dikembalikan menjadi HRESULT
. Misalnya, lihat dua metode C# COM berikut yang diterjemahkan ke tanda tangan asli yang sama:
int Add(int a, int b);
void Add(int a, int b, out int sum);
HRESULT Add(int a, int b, /* out */ int* sum);
PreserveSig di COM
Semua metode COM dalam C# diharapkan menggunakan tanda tangan yang diterjemahkan secara default. Untuk menggunakan dan mengekspor metode tanpa terjemahan tanda tangan dan penanganan HRESULT
nilai, tambahkan ke PreserveSigAttribute metode antarmuka COM. Ketika atribut diterapkan ke metode, tidak ada terjemahan yang dilakukan ke tanda tangan, dan pengecualian tidak dilemparkan untuk nilai yang HRESULT
gagal. Ini berlaku untuk COM bawaan dan COM yang dihasilkan sumber. Misalnya, lihat tanda tangan metode C# berikut dengan PreserveSig
atribut dan tanda tangan asli yang sesuai.
[PreserveSig]
int Add(int a, int b, out int sum);
HRESULT Add(int a, int b, int* sum);
Ini dapat berguna jika metode mungkin mengembalikan nilai berbeda HRESULT
yang bukan kegagalan, tetapi harus ditangani secara berbeda. Misalnya, beberapa metode mungkin mengembalikan nilai S_FALSE
ketika metode tidak gagal tetapi hanya mengembalikan hasil parsial, dan S_OK
ketika mengembalikan semua hasil.
PreserveSig
dengan P/Invokes
Atribut ini DllImportAttribute juga memiliki bool PreserveSig
bidang yang berfungsi mirip dengan PreserveSigAttribute
, tetapi default ke true
. Untuk menunjukkan bahwa runtime harus menerjemahkan tanda tangan terkelola dan menangani HRESULT
yang dikembalikan, atur PreserveSig
bidang ke false
di DllImportAttribute
. Misalnya, lihat tanda tangan berikut dari dua P/Pemanggilan ke metode asli yang sama, satu dengan diatur ke false
, dan satu dengan PreserveSig
tanda tangan kiri ke nilai defaulttrue
.
[DllImport("shlwapi.dll", EntryPoint = "SHAutoComplete", ExactSpelling = true, PreserveSig = false)]
public static extern void SHAutoComplete(IntPtr hwndEdit, SHAutoCompleteFlags dwFlags);
[DllImport("shlwapi.dll", EntryPoint = "SHAutoComplete", ExactSpelling = true)]
public static extern int SHAutoCompleteHRESULT(IntPtr hwndEdit, SHAutoCompleteFlags dwFlags);
Catatan
P/Invokes yang dihasilkan sumber, yang menggunakan LibraryImportAttribute, tidak PreserveSig
memiliki bidang. Kode yang dihasilkan selalu mengasumsikan tanda tangan asli dan terkelola identik. Untuk informasi selengkapnya, lihat P/Invokes yang dihasilkan sumber.
Menangani HRESULT
nilai secara manual
Saat memanggil PreserveSig
metode yang mengembalikan HRESULT
, Anda dapat menggunakan ThrowExceptionForHR metode untuk melemparkan pengecualian yang sesuai jika HRESULT
menunjukkan kegagalan. Demikian pula, saat menerapkan PreserveSig
metode, Anda dapat menggunakan GetHRForException metode untuk mengembalikan HRESULT
yang menunjukkan nilai yang sesuai untuk pengecualian.
HRESULT Marsekal sebagai struktur
Saat menggunakan PreserveSig
metode, int
diharapkan menjadi jenis terkelola untuk HRESULT
. Namun, menggunakan struct 4-byte kustom sebagai jenis pengembalian memungkinkan Anda menentukan metode dan properti pembantu HRESULT
yang dapat menyederhanakan bekerja dengan . Dalam marshalling bawaan, ini bekerja secara otomatis. Untuk menggunakan struct int
sebagai representasi terkelola dari HRESULT
dalam marshalling yang dihasilkan sumber, tambahkan MarshalAsAttribute atribut dengan Error sebagai argumen . Kehadiran atribut ini menginterpretir kembali bit HRESULT
sebagai struct.