Bagikan melalui


Cara: Bermigrasi ke /clr

Artikel ini membahas masalah yang muncul saat mengompilasi kode asli dengan /clr. (Untuk informasi selengkapnya, lihat /clr (Kompilasi Runtime Bahasa Umum).) /clr memungkinkan kode C++ asli untuk dipanggil dan dipanggil dari rakitan .NET selain kode C++ asli lainnya. Untuk informasi selengkapnya tentang keuntungan mengkompilasi dengan /clr, lihat Rakitan Campuran (Asli dan Terkelola) dan Interoperabilitas Asli dan .NET.

Masalah umum saat mengkompilasi proyek pustaka /clr

Visual Studio berisi beberapa masalah yang diketahui saat mengkompilasi proyek pustaka dengan /clr:

  • Kode Anda dapat mengkueri jenis saat runtime dengan CRuntimeClass::FromName. Namun, jika jenis berada dalam DLL MSIL (dikompilasi dengan /clr), panggilan ke FromName mungkin gagal jika terjadi sebelum konstruktor statis berjalan di DLL terkelola. (Anda tidak akan melihat masalah ini jika FromName panggilan terjadi setelah kode dijalankan di DLL terkelola.) Untuk mengatasi masalah ini, Anda dapat memaksa konstruksi konstruktor statis terkelola: menentukan fungsi di DLL terkelola, mengekspornya, dan memanggilnya dari aplikasi MFC asli. Contohnya:

    // MFC extension DLL Header file:
    __declspec( dllexport ) void EnsureManagedInitialization () {
       // managed code that won't be optimized away
       System::GC::KeepAlive(System::Int32::MaxValue);
    }
    

Mengkompilasi dengan Visual C++

Sebelum Anda menggunakan /clr modul apa pun dalam proyek Anda, pertama-tama kompilasi dan tautkan proyek asli Anda dengan Visual Studio.

Langkah-langkah berikut, diikuti secara berurutan, menyediakan jalur termampu ke /clr kompilasi. Penting untuk mengkompilasi dan menjalankan proyek Anda setelah setiap langkah ini.

Memutakhirkan dari versi Visual Studio yang lebih lama

Jika Anda memutakhirkan Visual Studio dari versi yang lebih lama, Anda mungkin melihat kesalahan pengkompilasi yang terkait dengan kesuaian Standard C++ yang ditingkatkan di Visual Studio.

Proyek yang dibangun dengan versi Visual Studio yang lebih lama juga harus terlebih dahulu dikompilasi tanpa /clr. Visual Studio sekarang telah meningkatkan kesuaian Standard C++ dan beberapa perubahan yang melanggar. Perubahan yang kemungkinan memerlukan perhatian paling besar adalah Fitur Keamanan di CRT. Kode yang menggunakan CRT kemungkinan akan menghasilkan peringatan penghentian. Peringatan ini dapat ditekan, tetapi bermigrasi ke versi fungsi CRT baru yang ditingkatkan keamanan lebih disukai , karena memberikan keamanan yang lebih baik dan dapat mengungkapkan masalah keamanan dalam kode Anda.

Memutakhirkan dari Ekstensi Terkelola untuk C++

Di Visual Studio 2005 dan versi yang lebih baru, kode yang ditulis dengan Ekstensi Terkelola untuk C++ tidak akan dikompilasi di bawah /clr.

Mengonversi kode C ke C++

Meskipun Visual Studio akan mengkompilasi file C, perlu untuk mengonversinya ke C++ untuk /clr kompilasi. Nama file aktual tidak harus diubah; Anda dapat menggunakan /Tp (lihat /Tc, , /TC/Tp, /TP (Tentukan jenis file sumber).) Meskipun file kode sumber C++ diperlukan untuk /clr, tidak perlu merefaktor kode Anda untuk menggunakan paradigma berorientasi objek.

Kode C kemungkinan memerlukan perubahan saat dikompilasi sebagai file C++. Aturan keamanan jenis C++ ketat, sehingga konversi jenis harus dibuat eksplisit dengan cast. Misalnya, malloc mengembalikan penunjuk kekosongan, tetapi dapat ditetapkan ke penunjuk ke jenis apa pun di C dengan cast:

int* a = malloc(sizeof(int));   // C code
int* b = (int*)malloc(sizeof(int));   // C++ equivalent

Penunjuk fungsi juga benar-benar aman jenis di C++, sehingga kode C berikut memerlukan modifikasi. Di C++, yang terbaik adalah membuat typedef yang menentukan jenis penunjuk fungsi, lalu gunakan jenis tersebut untuk mentransmisikan penunjuk fungsi:

NewFunc1 = GetProcAddress( hLib, "Func1" );   // C code
typedef int(*MYPROC)(int);   // C++ equivalent
NewFunc2 = (MYPROC)GetProcAddress( hLib, "Func2" );

C++ juga mengharuskan fungsi diprototi atau sepenuhnya ditentukan sebelum dapat direferensikan atau dipanggil.

Pengidentifikasi yang digunakan dalam kode C yang kebetulan merupakan kata kunci di C++ (seperti virtual, , , newbooldelete, true, falsedll.) harus diganti namanya. Perubahan ini umumnya dapat dilakukan dengan operasi pencarian dan penggantian sederhana.

COMObj1->lpVtbl->Method(COMObj, args);  // C code
COMObj2->Method(args);  // C++ equivalent

Mengonfigurasi ulang pengaturan proyek

Setelah proyek Anda dikompilasi dan dijalankan di Visual Studio, Anda harus membuat konfigurasi proyek baru daripada /clr memodifikasi konfigurasi default. /clr tidak kompatibel dengan beberapa opsi pengkompilasi. Membuat konfigurasi terpisah memungkinkan Anda membangun proyek sebagai asli atau terkelola. Ketika /clr dipilih dalam kotak dialog halaman properti, pengaturan proyek yang tidak kompatibel dengan /clr dinonaktifkan. (Opsi yang dinonaktifkan tidak dipulihkan secara otomatis jika /clr nanti tidak dipilih.)

Membuat konfigurasi proyek baru

Anda dapat menggunakan opsi Salin Pengaturan Dari di Kotak Dialog Konfigurasi Proyek Baru (Konfigurasi>Solusi Aktif Build>Configuration Manager>Baru) untuk membuat konfigurasi proyek berdasarkan pengaturan proyek yang ada. Buat salinan konfigurasi Anda sekali untuk konfigurasi Debug, dan sekali untuk Konfigurasi rilis. Perubahan berikutnya kemudian dapat diterapkan ke /clrkonfigurasi -spesifik saja, membiarkan konfigurasi proyek asli tetap utuh.

Proyek yang menggunakan aturan build kustom mungkin memerlukan perhatian ekstra.

Langkah ini memiliki implikasi yang berbeda untuk proyek yang menggunakan makefiles. Dalam hal ini, target build terpisah dapat dikonfigurasi, atau versi khusus untuk /clr kompilasi dapat dibuat dari salinan aslinya.

Mengubah pengaturan proyek

/clr dapat dipilih di lingkungan pengembangan dengan mengikuti instruksi di /clr (Common Language Runtime Compilation). Seperti disebutkan sebelumnya, langkah ini akan secara otomatis menonaktifkan pengaturan proyek yang bertentangan.

Catatan

Saat memutakhirkan pustaka terkelola atau proyek layanan web dari Visual Studio 2003, /Zl opsi pengkompilasi ditambahkan ke halaman properti Baris Perintah. Ini menyebabkan kesalahan LNK2001. Hapus /Zl dari halaman properti Baris Perintah untuk mengatasi kesalahan. Untuk informasi selengkapnya, lihat /Zl (Hilangkan nama pustaka default) dan Atur properti kompilator dan build.

Untuk proyek yang dibangun dengan makefiles, opsi kompilator yang tidak kompatibel harus dinonaktifkan secara manual setelah /clr ditambahkan. Untuk informasi tentang opsi pengkompilasi yang tidak kompatibel dengan /clr, lihat /clr batasan.

Header yang telah dikompresi

Header yang telah dikompresi didukung di bawah /clr. Namun, jika Anda hanya mengkompilasi beberapa file CPP Anda dengan /clr (mengkompilasi sisanya sebagai asli), beberapa perubahan diperlukan. Header yang telah dikommpilasi yang dihasilkan dengan /clr tidak kompatibel dengan header yang telah dikommpilasikan yang dihasilkan tanpa /clr, karena /clr menghasilkan dan memerlukan metadata. Modul yang dikompilasi dengan /clr tidak dapat menggunakan header yang telah dikompilasi sebelumnya yang tidak menyertakan metadata, dan non-modul/clr tidak dapat menggunakan file header yang telah dikompilasi sebelumnya yang berisi metadata.

Cara term mudah untuk mengkompilasi proyek di mana beberapa modul dikompilasi dengan adalah dengan /clr menonaktifkan header yang telah dikompilasi sepenuhnya. (Dalam dialog Halaman Properti proyek, buka Simpul C/C++ , dan pilih Header yang Telah Dikompilasi sebelumnya. Kemudian ubah properti Buat/Gunakan Header yang Telah Dikommpilasikan ke "Tidak Menggunakan Header yang Telah Dikompresi".)

Namun, terutama untuk proyek besar, header yang telah dikompilasi memberikan kecepatan kompilasi yang jauh lebih baik, sehingga menonaktifkan fitur ini tidak diinginkan. Dalam hal ini, yang terbaik adalah mengonfigurasi /clr dan non-file/clr untuk menggunakan header terpisah yang telah dikompilasi. Anda dapat mengonfigurasinya dalam satu langkah: Pilih beberapa modul untuk dikompilasi dengan /clr menggunakan Penjelajah Solusi. Klik kanan pada grup, dan pilih Properti. Kemudian, ubah properti Buat/Gunakan PCH Melalui File dan File Header yang Telah Dikompresi untuk menggunakan nama file header dan file PCH yang berbeda.

Memperbaiki kesalahan

Mengkompilasi kode Anda dengan /clr dapat mengakibatkan kesalahan kompiler, linker, atau runtime. Bagian ini membahas masalah yang paling umum.

Penggabungan metadata

Versi jenis data yang berbeda dapat menyebabkan linker gagal karena metadata yang dihasilkan untuk dua jenis tidak cocok. (Kesalahan terjadi saat Anda menentukan anggota jenis secara kondisional, tetapi kondisinya tidak sama untuk semua file CPP yang menggunakan jenis tersebut.) Dalam hal ini, linker gagal, hanya melaporkan nama simbol dan nama file OBJ kedua tempat jenis ditentukan. Anda mungkin merasa berguna untuk memutar urutan file OBJ dikirim ke linker, untuk menemukan lokasi versi jenis data lainnya.

Kebuntuan kunci loader

"Kebuntuan kunci loader" dapat terjadi, tetapi deterministik dan terdeteksi dan dilaporkan saat runtime. Lihat Inisialisasi Rakitan Campuran untuk latar belakang, panduan, dan solusi terperinci.

Ekspor data

Mengekspor data DLL rawan kesalahan, dan tidak disarankan dalam /clr kode. Ini karena inisialisasi bagian data DLL tidak dijamin sampai beberapa bagian terkelola DLL dijalankan. Referensi metadata dengan #using direktif.

Visibilitas jenis

Jenis asli secara private default. private Jenis asli tidak terlihat di luar DLL. Atasi kesalahan ini dengan menambahkan public ke jenis ini.

Masalah titik mengambang dan perataan

__controlfp tidak didukung dalam runtime bahasa umum. (Untuk informasi selengkapnya, lihat _control87, , __control87_2_controlfp.) CLR juga tidak menghormati align.

Inisialisasi COM

Common Language Runtime menginisialisasi COM secara otomatis ketika modul diinisialisasi (ketika COM diinisialisasi secara otomatis dilakukan sebagai MTA). Akibatnya, secara eksplisit menginisialisasi hasil COM menghasilkan kode yang menunjukkan bahwa COM sudah diinisialisasi. Mencoba menginisialisasi COM secara eksplisit dengan satu model utas ketika CLR telah menginisialisasi COM ke model utas lain dapat menyebabkan aplikasi Anda gagal.

Runtime bahasa umum memulai COM sebagai MTA secara default; gunakan /CLRTHREADATTRIBUTE (Atur atribut utas CLR) untuk memodifikasi model COM.

Masalah performa

Anda mungkin melihat penurunan performa ketika metode C++ asli yang dihasilkan ke MSIL dipanggil secara tidak langsung (melalui panggilan fungsi virtual atau dengan menggunakan penunjuk fungsi). Untuk mempelajari lebih lanjut, lihat Double Thunking.

Saat berpindah dari asli ke MSIL, Anda akan melihat peningkatan ukuran set kerja Anda. Peningkatan ini terjadi karena runtime bahasa umum menyediakan banyak fitur untuk memastikan bahwa program berjalan dengan benar. Jika aplikasi Anda /clr tidak berjalan dengan benar, Anda mungkin ingin mengaktifkan Compiler Warning off-by-default (level 1 dan 3) C4793.

Program lumpuh saat dimatikan

Dalam beberapa kasus, CLR dapat dimatikan sebelum kode terkelola Anda selesai berjalan. Penggunaan std::set_terminate dan SIGTERM dapat menyebabkan pematian. Untuk informasi selengkapnya, lihat signal konstanta dan set_terminate.

Menggunakan fitur Visual C++ baru

Setelah aplikasi Anda dikompilasi, tautan, dan eksekusi, Anda dapat mulai menggunakan fitur .NET dalam modul apa pun yang dikompilasi dengan /clr. Untuk informasi selengkapnya, lihat Ekstensi Komponen untuk Platform Runtime.

Untuk informasi selengkapnya tentang pemrograman .NET di Visual C++, lihat:

Baca juga

Rakitan Campuran (Asli dan Terkelola)