Udostępnij za pośrednictwem


Instrukcje: migrowanie do /clr

W tym artykule omówiono problemy występujące podczas kompilowania kodu natywnego za pomocą polecenia /clr. (Aby uzyskać więcej informacji, zobacz /clr (kompilacja środowiska uruchomieniowego języka wspólnego)). /clr umożliwia wywoływanie i wywoływanie natywnego kodu C++ z zestawów platformy .NET oprócz innego natywnego kodu C++. Aby uzyskać więcej informacji na temat zalet kompilowania za pomocą /clrprogramu , zobacz Zestawy mieszane (natywne i zarządzane) oraz Współdziałanie natywne i .NET.

Znane problemy z kompilowaniem projektów biblioteki za pomocą polecenia /clr

Program Visual Studio zawiera niektóre znane problemy podczas kompilowania projektów biblioteki za pomocą polecenia /clr:

  • Kod może wykonywać zapytania dotyczące typów w czasie wykonywania za pomocą polecenia CRuntimeClass::FromName. Jeśli jednak typ znajduje się w biblioteki DLL MSIL (skompilowanej za pomocą /clrpolecenia ), wywołanie FromName metody może zakończyć się niepowodzeniem, jeśli wystąpi przed uruchomieniem konstruktorów statycznych w zarządzanej biblioteki DLL. (Ten problem nie zostanie wyświetlony, jeśli FromName wywołanie zostanie wykonane po wykonaniu kodu w zarządzanej biblioteki DLL). Aby obejść ten problem, możesz wymusić konstruowanie zarządzanego konstruktora statycznego: zdefiniować funkcję w zarządzanej bibliotece DLL, wyeksportować ją i wywołać z natywnej aplikacji MFC. Na przykład:

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

Kompilowanie przy użyciu języka Visual C++

Przed użyciem /clr dowolnego modułu w projekcie najpierw skompiluj i połącz projekt macierzysty z programem Visual Studio.

Poniższe kroki, wykonywane w podanej kolejności, zapewniają najłatwiejszą ścieżkę /clr do kompilacji. Ważne jest, aby skompilować i uruchomić projekt po każdym z tych kroków.

Uaktualnianie z wcześniejszych wersji programu Visual Studio

W przypadku uaktualniania programu Visual Studio z wcześniejszej wersji mogą pojawić się błędy kompilatora związane z rozszerzoną zgodnością standardowego języka C++ w programie Visual Studio.

Projekty skompilowane przy użyciu wcześniejszych wersji programu Visual Studio powinny być również kompilowane bez /clrprogramu . Program Visual Studio zwiększył zgodność standardowego języka C++ i pewne zmiany powodujące niezgodność. Zmiany, które prawdopodobnie będą wymagały największej uwagi, to funkcje zabezpieczeń w CRT. Kod korzystający z narzędzia CRT prawdopodobnie generuje ostrzeżenia o wycofaniu. Te ostrzeżenia można pominąć, ale migracja do nowych wersji rozszerzonych zabezpieczeń funkcji CRT jest preferowana, ponieważ zapewniają lepsze zabezpieczenia i mogą ujawnić problemy z zabezpieczeniami w kodzie.

Uaktualnianie z rozszerzeń zarządzanych dla języka C++

W programie Visual Studio 2005 i nowszych wersjach kod napisany za pomocą rozszerzeń zarządzanych dla języka C++ nie będzie kompilowany w programie /clr.

Konwertowanie kodu C na C++

Mimo że program Visual Studio skompiluje pliki C, konieczne jest przekonwertowanie ich na język C++ na potrzeby /clr kompilacji. Rzeczywista nazwa pliku nie musi zostać zmieniona; Można użyć /Tp (zobacz /Tc, , /Tp, /TC/TP (Określ typ pliku źródłowego)). Mimo że pliki kodu źródłowego języka C++ są wymagane dla /clrprogramu , nie jest konieczne refaktoryzowanie kodu w celu używania paradygmatów zorientowanych na obiekty.

Kod języka C może wymagać zmian podczas kompilowania jako pliku C++. Reguły bezpieczeństwa typów języka C++ są ścisłe, dlatego konwersje typów muszą być jawne z rzutami. Na przykład malloc zwraca wskaźnik void, ale może być przypisany do wskaźnika do dowolnego typu w języku C z rzutowania:

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

Wskaźniki funkcji są również ściśle bezpieczne dla typów w języku C++, więc poniższy kod języka C wymaga modyfikacji. W języku C++najlepiej utworzyć element typedef definiujący typ wskaźnika funkcji, a następnie użyć tego typu do rzutowania wskaźników funkcji:

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

Język C++ wymaga również, aby funkcje były prototypowane lub w pełni zdefiniowane, zanim będą mogły być przywoływane lub wywoływane.

Należy zmienić nazwy identyfikatorów używanych w kodzie języka C, które są słowami kluczowymi w języku C++ (na przykład virtual, , newbooldelete, true, falseitp.). Tę zmianę można zazwyczaj wykonać przy użyciu prostych operacji wyszukiwania i zastępowania.

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

Ponowne konfigurowanie ustawień projektu

Po skompilowaniu i uruchomieniu projektu w programie Visual Studio należy utworzyć nowe konfiguracje /clr projektu zamiast modyfikować konfiguracje domyślne. /clr jest niezgodny z niektórymi opcjami kompilatora. Tworzenie oddzielnych konfiguracji umożliwia tworzenie projektu jako natywnego lub zarządzanego. Po /clr wybraniu w oknie dialogowym strony właściwości ustawienia projektu niezgodne z /clr programem są wyłączone. (Wyłączone opcje nie są automatycznie przywracane, jeśli /clr zostaną później niezaznaczone).

Tworzenie nowych konfiguracji projektu

Możesz użyć opcji Kopiuj ustawienia Z w oknie dialogowym Nowa konfiguracja projektu (Utwórz>konfigurację aktywnego rozwiązania>programu Configuration Manager>Nowy), aby utworzyć konfigurację projektu na podstawie istniejących ustawień projektu. Utwórz kopię konfiguracji raz dla konfiguracji debugowania i raz dla konfiguracji wydania. Kolejne zmiany można następnie zastosować tylko do /clrkonfiguracji specyficznych dla projektu, pozostawiając oryginalne konfiguracje projektu bez zmian.

Projekty korzystające z niestandardowych reguł kompilacji mogą wymagać dodatkowej uwagi.

Ten krok ma różne konsekwencje dla projektów korzystających z plików make. W takim przypadku można skonfigurować oddzielny element docelowy kompilacji lub wersję specyficzną dla /clr kompilacji na podstawie kopii oryginalnej.

Zmienianie ustawień projektu

/clr Można wybrać w środowisku projektowym, postępując zgodnie z instrukcjami w / clr (kompilacja środowiska uruchomieniowego języka wspólnego). Jak wspomniano wcześniej, ten krok spowoduje automatyczne wyłączenie ustawień projektu powodującego konflikt.

Uwaga

Podczas uaktualniania biblioteki zarządzanej lub projektu usługi internetowej z programu Visual Studio 2003 /Zl opcja kompilatora jest dodawana do strony właściwości Wiersza polecenia. Powoduje to błędy LNK2001. Usuń /Zl ze strony właściwości Wiersza polecenia, aby usunąć błędy. Aby uzyskać więcej informacji, zobacz /Zl (Pomijanie domyślnej nazwy biblioteki) i Ustawianie właściwości kompilatora i kompilacji.

W przypadku projektów utworzonych za pomocą plików make, niezgodne opcje kompilatora muszą być wyłączone ręcznie po /clr dodaniu. Aby uzyskać informacje na temat opcji kompilatora, które nie są zgodne z /clrprogramem , zobacz /clr ograniczenia.

Prekompilowane nagłówki

Prekompilowane nagłówki są obsługiwane w obszarze /clr. Jeśli jednak tylko skompilujesz niektóre pliki /clr CPP (kompilując resztę jako natywną), wymagane są pewne zmiany. Wstępnie skompilowane nagłówki wygenerowane /clr za pomocą elementu nie są zgodne ze wstępnie skompilowanym nagłówkami wygenerowanymi bez /clrelementu , ponieważ /clr generuje i wymaga metadanych. Moduły skompilowane /clr za pomocą polecenia nie mogą używać wstępnie skompilowanych nagłówków, które nie zawierają metadanych, a moduły inne/clr niż moduły nie mogą używać wstępnie skompilowanych plików nagłówkowych zawierających metadane.

Najprostszym sposobem skompilowania projektu, w którym są kompilowane /clr niektóre moduły, jest całkowite wyłączenie prekompilowanych nagłówków. (W oknie dialogowym Strony właściwości projektu otwórz okno dialogoweWęzeł C/C++ i wybierz pozycję Prekompilowane nagłówki. Następnie zmień właściwość Create/Use Precompiled Headers na "Not Using Precompiled Headers".

Jednak szczególnie w przypadku dużych projektów prekompilowane nagłówki zapewniają znacznie lepszą szybkość kompilacji, więc wyłączenie tej funkcji nie jest pożądane. W takim przypadku najlepszym rozwiązaniem jest skonfigurowanie /clr plików innych niż i do/clr używania oddzielnych prekompilowanych nagłówków. Można je skonfigurować w jednym kroku: wybierz wiele modułów do skompilowania /clr przy użyciu Eksplorator rozwiązań. Kliknij prawym przyciskiem myszy grupę, a następnie wybierz pozycję Właściwości. Następnie zmień zarówno właściwości Create/Use PCH Through File and Precompiled Header File ,aby użyć innej nazwy pliku nagłówka i pliku PCH, odpowiednio.

Naprawianie błędów

Kompilowanie kodu za pomocą /clr polecenia może spowodować błędy kompilatora, konsolidatora lub środowiska uruchomieniowego. W tej sekcji omówiono najczęstsze problemy.

Scalanie metadanych

Różne wersje typów danych mogą spowodować niepowodzenie konsolidatora, ponieważ metadane wygenerowane dla tych dwóch typów nie są zgodne. (Błędy występują podczas warunkowego definiowania składowych typu, ale warunki nie są takie same dla wszystkich plików CPP, które używają typu). W takim przypadku konsolidator kończy się niepowodzeniem, zgłaszając tylko nazwę symbolu i nazwę drugiego pliku OBJ, w którym zdefiniowano typ. Może się okazać, że warto obrócić kolejność wysyłania plików OBJ do konsolidatora, aby odnaleźć lokalizację innej wersji typu danych.

Zakleszczenie blokady modułu ładującego

Może wystąpić "zakleszczenie blokady modułu ładującego", ale jest deterministyczne i wykrywane i zgłaszane w czasie wykonywania. Zobacz Inicjowanie zestawów mieszanych , aby uzyskać szczegółowe informacje, wskazówki i rozwiązania.

Eksporty danych

Eksportowanie danych dll jest podatne na błędy i nie jest zalecane w /clr kodzie. Wynika to z faktu, że inicjowanie sekcji danych biblioteki DLL nie jest gwarantowane, dopóki część zarządzana biblioteki DLL nie zostanie wykonana. Odwołania do metadanych z dyrektywami#using.

Widoczność typu

Typy natywne są private domyślnie. private Typ natywny nie jest widoczny poza biblioteką DLL. Rozwiąż ten błąd, dodając public do tych typów.

Problemy z zmiennoprzecinką i wyrównaniem

__controlfp program nie jest obsługiwany w środowisku uruchomieniowym języka wspólnego. (Aby uzyskać więcej informacji, zobacz _control87, _controlfp, __control87_2.) ClR również nie szanuje align.

Inicjowanie modelu COM

Środowisko uruchomieniowe języka wspólnego automatycznie inicjuje com po zainicjowaniu modułu (po zainicjowaniu modelu COM jest on wykonywany automatycznie jako MTA). W związku z tym jawne inicjowanie kodów zwracanych com wskazuje, że com jest już zainicjowany. Próba jawnego zainicjowania modelu COM przy użyciu jednego modelu wątkowego, gdy CLR zainicjował już model COM do innego modelu wątkowego, może spowodować niepowodzenie aplikacji.

Środowisko uruchomieniowe języka wspólnego domyślnie uruchamia com jako MTA; use /CLRTHREADATTRIBUTE (Ustaw atrybut wątku CLR) w celu zmodyfikowania modelu COM.

Problemy z wydajnością

Wydajność może być zmniejszona, gdy natywne metody języka C++ generowane w języku MSIL są wywoływane pośrednio (za pośrednictwem wywołań funkcji wirtualnych lub przy użyciu wskaźników funkcji). Aby dowiedzieć się więcej, zobacz Double Thunking.

Podczas przechodzenia z natywnego do MSIL zauważysz wzrost rozmiaru zestawu roboczego. Ten wzrost występuje, ponieważ środowisko uruchomieniowe języka wspólnego udostępnia wiele funkcji, aby upewnić się, że programy działają poprawnie. Jeśli aplikacja /clr nie działa poprawnie, możesz włączyć domyślne ostrzeżenie kompilatora (poziom 1 i 3) C4793.

Program ulega awarii po zamknięciu

W niektórych przypadkach clR może zostać zamknięty przed zakończeniem działania kodu zarządzanego. std::set_terminate Użycie polecenia i SIGTERM może spowodować zamknięcie. Aby uzyskać więcej informacji, zobacz signal stałe i set_terminate.

Korzystanie z nowych funkcji języka Visual C++

Po skompilowaniu, łączem i uruchomieniu aplikacji możesz rozpocząć korzystanie z funkcji platformy .NET w dowolnym module skompilowanym za pomocą /clrpolecenia . Aby uzyskać więcej informacji, zobacz Rozszerzenia składników dla platform środowiska uruchomieniowego.

Aby uzyskać więcej informacji na temat programowania .NET w języku Visual C++, zobacz:

Zobacz też

Zestawy mieszane (natywne i zarządzane)