Rumah >pembangunan bahagian belakang >C++ >Bagaimana untuk Mengelakkan System.AccessViolationException Apabila Melepasi Rentetan Antara C# dan C DLL?
Melalui Rentetan antara C# dan C DLL: Contoh Minimal
Pernyataan Masalah
Walaupun mengikut pendekatan yang kelihatan mudah, menghantar rentetan antara C# dan C DLL melalui interop menyebabkan System.AccessViolationException. Kod dalam kedua-dua bahasa kelihatan betul, menimbulkan kekeliruan tentang punca isu.
Kod C
Kod C mentakrifkan fungsi, concat, yang menggabungkan dua rentetan dan mengembalikan hasilnya. Fungsi ini ditandakan untuk eksport ke DLL menggunakan __declspec(dllexport).
extern "C" { string concat(string a, string b){ return a + b; } }
Kod C#
Dalam C#, kod mengimport fungsi concat menggunakan DllImport. CallingConvention ditetapkan kepada Cdecl untuk memadankan konvensyen C.
[DllImport("*****.dll", CallingConvention = CallingConvention.Cdecl)] static extern string concat(string a, string b);
Pengecualian dan Analisis
Memanggil concat("a", "b") dalam lontaran C# a System.AccessViolationException. Pengecualian ini menunjukkan bahawa akses memori tidak sah berlaku dalam kod asli.
Penyelesaian: Jenis Interop-Compatible
Penyebab isu ini terletak pada penggunaan C std :: rentetan merentasi sempadan interop. C# tidak boleh mencipta atau mengendalikan objek std::string secara langsung. Sebaliknya, jenis serasi interop mesti digunakan untuk pertukaran data.
Jenis Data Mesra Interop
Jenis interop yang sesuai termasuk tatasusunan aksara yang ditamatkan nol untuk menghantar rentetan daripada C# kepada C . Apabila menghantar rentetan daripada C ke C#, StringBuilder boleh digunakan, dengan pemanggil memperuntukkan penimbal dan penerima menulis ke dalamnya.
Kod Diubahsuai
Dalam C , fungsi concat boleh diisytiharkan dengan parameter char* dan int untuk menerima penimbal dannya panjang.
extern "C" { void concat(char *str, int len) { // Concatenate strings and write to buffer } }
Dalam C#, StringBuilder boleh digunakan.
[DllImport("...", CallingConvention = CallingConvention.Cdecl)] static extern void concat(StringBuilder str, int len); .... StringBuilder sb = new StringBuilder(10); concat(sb, sb.Capacity);
Dengan menggunakan jenis rentetan serasi interop, pertukaran rentetan antara C# dan C DLL boleh dipermudahkan dengan berkesan.
Atas ialah kandungan terperinci Bagaimana untuk Mengelakkan System.AccessViolationException Apabila Melepasi Rentetan Antara C# dan C DLL?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!