Bagikan melalui


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 HRESULTyang 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.

Lihat juga