Postupy: Migrace na /clr
Tento článek popisuje problémy, ke kterým dochází při kompilaci nativního kódu s /clr
. (Další informace naleznete v tématu /clr (Common Language Runtime Compilation).) /clr
umožňuje nativní kód jazyka C++ vyvolat a vyvolat z sestavení .NET kromě jiného nativního kódu jazyka C++. Další informace o výhodách kompilace pomocí /clr
, viz smíšené (nativní a spravované) sestavení a nativní a .NET interoperability.
Známé problémy při kompilaci projektů knihovny pomocí /clr
Visual Studio obsahuje některé známé problémy při kompilaci projektů knihovny pomocí /clr
:
Kód může za běhu
CRuntimeClass::FromName
dotazovat typy. Pokud je však typ v knihovně MSIL DLL (kompilováno pomocí/clr
), může voláníFromName
selhat, pokud dojde před spuštěním statických konstruktorů ve spravované knihovně DLL. (Tento problém se nezobrazí, pokud seFromName
volání stane po spuštění kódu ve spravované knihovně DLL.) Chcete-li tento problém vyřešit, můžete vynutit vytvoření spravovaného statického konstruktoru: definovat funkci ve spravované knihovně DLL, exportovat ji a vyvolat ji z nativní aplikace MFC. Příklad:// MFC extension DLL Header file: __declspec( dllexport ) void EnsureManagedInitialization () { // managed code that won't be optimized away System::GC::KeepAlive(System::Int32::MaxValue); }
Kompilace v jazyce Visual C++
Před použitím /clr
libovolného modulu v projektu nejprve zkompilujte a propojte svůj nativní projekt se sadou Visual Studio.
Následující kroky, následované v pořadí, poskytují nejjednodušší cestu k /clr
kompilaci. Po každém z těchto kroků je důležité zkompilovat a spustit projekt.
Upgrade ze starších verzí sady Visual Studio
Pokud upgradujete Visual Studio ze starší verze, můžou se v sadě Visual Studio zobrazit chyby kompilátoru související s vylepšeným standardem C++.
Projekty vytvořené se staršími verzemi sady Visual Studio by se měly nejprve zkompilovat i bez /clr
. Visual Studio teď zvýšilo shodu standardu C++ a některé zásadní změny. Změny, které pravděpodobně vyžadují největší pozornost, jsou funkce zabezpečení v CRT. Kód, který používá CRT, pravděpodobně způsobí upozornění na vyřazení. Tato upozornění je možné potlačit, ale migrace na nové verze funkcí CRT s rozšířeným zabezpečením je upřednostňovaná, protože poskytují lepší zabezpečení a můžou odhalit problémy se zabezpečením ve vašem kódu.
Upgrade z Spravovaná rozšíření jazyka C++
V sadě Visual Studio 2005 a novějších verzích se kód napsaný pomocí Spravovaná rozšíření jazyka C++ nebude kompilovat v části /clr
.
Převod kódu jazyka C na C++
I když Visual Studio kompiluje soubory jazyka C, je nutné je převést na jazyk C++ pro /clr
kompilaci. Skutečný název souboru nemusí být změněn; můžete použít /Tp
(viz/Tc
, /Tp
, /TC
, , /TP
(Zadat typ zdrojového souboru).) I když jsou pro soubory zdrojového kódu C++ potřeba /clr
, není nutné refaktorovat kód tak, aby používal objektově orientované paradigmata.
Kód jazyka C bude pravděpodobně vyžadovat změny při kompilaci jako souboru C++. Pravidla zabezpečení typu C++ jsou striktní, takže převody typů musí být explicitní s přetypování. Například malloc vrátí ukazatel void, ale lze ho přiřadit k libovolnému typu v jazyce C s přetypování:
int* a = malloc(sizeof(int)); // C code
int* b = (int*)malloc(sizeof(int)); // C++ equivalent
Ukazatele funkcí jsou v jazyce C++ také přísně typově bezpečné, takže následující kód jazyka C vyžaduje úpravy. V jazyce C++ je nejlepší vytvořit typedef
definici typu ukazatele funkce a pak tento typ použít k přetypování ukazatelů na funkce:
NewFunc1 = GetProcAddress( hLib, "Func1" ); // C code
typedef int(*MYPROC)(int); // C++ equivalent
NewFunc2 = (MYPROC)GetProcAddress( hLib, "Func2" );
Jazyk C++ také vyžaduje, aby funkce byly prototypovány nebo plně definovány dříve, než je lze odkazovat nebo vyvolat.
Identifikátory používané v kódu jazyka C, které se v jazyce C++ používají jako klíčová slova (například virtual
, new
, delete
, bool
, true
, false
atd.), musí být přejmenovány. Tuto změnu lze obecně provést pomocí jednoduchých operací hledání a nahrazení.
COMObj1->lpVtbl->Method(COMObj, args); // C code
COMObj2->Method(args); // C++ equivalent
Změna konfigurace nastavení projektu
Po kompilaci a spuštění projektu v sadě Visual Studio byste měli místo úprav výchozích konfigurací vytvořit nové konfigurace /clr
projektu. /clr
není kompatibilní s některými možnostmi kompilátoru. Vytváření samostatných konfigurací umožňuje sestavit projekt jako nativní nebo spravovaný. Pokud /clr
je vybrána v dialogovém okně stránky vlastností, nastavení projektu není kompatibilní s /clr
jsou zakázána. (Zakázané možnosti se automaticky neobnoví, pokud /clr
je později nevybrané.)
Vytvoření nových konfigurací projektu
Pomocí možnosti Kopírovat nastavení z v dialogovém okně Nová konfigurace projektu (Nová konfigurace> aktivního řešení buildu>Configuration Manageru>) můžete vytvořit konfiguraci projektu na základě existujícího nastavení projektu. Vytvořte kopii konfigurace jednou pro konfiguraci ladění a jednou pro konfiguraci vydané verze. Následné změny se pak dají použít pouze u /clr
konfigurací specifických pro konkrétní, takže původní konfigurace projektu zůstanou nedotčené.
Projekty, které používají vlastní pravidla sestavení, mohou vyžadovat zvláštní pozornost.
Tento krok má různé důsledky pro projekty, které používají soubory pravidel. V takovém případě je možné nakonfigurovat samostatný cíl sestavení nebo z kopie originálu lze vytvořit verzi specifickou pro /clr
kompilaci.
Změna nastavení projektu
/clr
je možné vybrat ve vývojovém prostředí podle pokynů v /clr (Common Language Runtime Compilation). Jak už bylo zmíněno dříve, tento krok automaticky zakáže konfliktní nastavení projektu.
Poznámka:
Při upgradu spravované knihovny nebo projektu webové služby ze sady Visual Studio 2003 se možnost kompilátoru /Zl
přidá na stránku vlastností příkazového řádku . To způsobuje chyby LNK2001. Pokud chcete chyby vyřešit, odeberte /Zl
ze stránky vlastností příkazového řádku . Další informace najdete v tématu /Zl
(Vynechání výchozího názvu knihovny) a nastavení vlastností kompilátoru a sestavení.
U projektů vytvořených pomocí souborů pravidel je nutné po přidání ručně /clr
zakázat nekompatibilní možnosti kompilátoru. Informace o možnostech kompilátoru, které nejsou kompatibilní /clr
, najdete v tématu /clr
Omezení.
Předkompilované hlavičky
Předkompilované hlavičky jsou podporovány v části /clr
. Pokud ale zkompilujete jenom některé soubory CPP ( /clr
kompilujete zbytek jako nativní), vyžadují se některé změny. Předkompilované hlavičky generované pomocí /clr
předkompilovaných hlaviček nejsou kompatibilní s předkompilovanými hlavičkami vygenerovanými bez /clr
, protože /clr
generuje a vyžaduje metadata. Moduly zkompilované pomocí /clr
předkompilovaných hlaviček, které neobsahují metadata,/clr
nemůžou používat předkompilované hlavičkové soubory, které obsahují metadata.
Nejjednodušší způsob, jak zkompilovat projekt, se /clr
kterým jsou některé moduly zkompilovány, je zcela zakázat předkompilované hlavičky. (V dialogovém okně Stránky vlastností projektu otevřete Uzel C/C++ a vyberte Předkompilované hlavičky. Potom změňte vlastnost Create/Use Precompiled Headers na "Not Using Precompiled Headers".)
Zejména u velkých projektů ale předkompilované hlavičky poskytují mnohem lepší rychlost kompilace, takže zakázání této funkce není žádoucí. V tomto případě je nejlepší nakonfigurovat /clr
soubory/clr
bez souborů tak, aby používaly samostatné předkompilované hlavičky. Můžete je nakonfigurovat v jednom kroku: Vícenásobný výběr modulů, které /clr
se mají zkompilovat pomocí Průzkumník řešení. Klikněte pravým tlačítkem na skupinu a vyberte Vlastnosti. Potom změňte vlastnosti Create/Use PCH Through File a Prekompiled Header File tak, aby používaly jiný název hlavičkového souboru a soubor PCH.
Oprava chyb
Kompilace kódu může vést k chybám /clr
kompilátoru, linkeru nebo modulu runtime. Tato část popisuje nejběžnější problémy.
Sloučení metadat
Rozdílové verze datových typů můžou způsobit selhání linkeru, protože metadata generovaná pro tyto dva typy se neshodují. (K chybám dochází při podmíněném definování členů typu, ale podmínky nejsou stejné pro všechny soubory CPP, které používají typ.) V tomto případě linker selže a hlásí pouze název symbolu a název druhého souboru OBJ, ve kterém byl typ definován. Může být užitečné otočit pořadí odesílání souborů OBJ do linkeru, abyste zjistili umístění jiné verze datového typu.
Zámek zavaděče
K zablokování zámku zavaděče může dojít, ale je deterministické a je zjištěno a hlášeno za běhu. Podrobné pokyny a řešení najdete v tématu Inicializace smíšených sestavení .
Exporty dat
Export dat knihovny DLL je náchylný k chybám a nedoporučuje se v /clr
kódu. Je to proto, že inicializace datového oddílu knihovny DLL není zaručena, dokud se nespustí některá spravovaná část knihovny DLL. Referenční metadata s direktivami#using
.
Viditelnost typů
Nativní typy jsou private
ve výchozím nastavení. Nativní private
typ není viditelný mimo knihovnu DLL. Vyřešte tuto chybu přidáním public
do těchto typů.
Problémy s plovoucí desetinou čárkou a zarovnáním
__controlfp
v modulu CLR (Common Language Runtime) se nepodporuje. (Další informace naleznete v tématu _control87
, _controlfp
__control87_2
.) CLR také nerespektuje align
.
Inicializace modelu COM
Modul CLR (Common Language Runtime) inicializuje model COM automaticky při inicializaci modulu (když se com inicializuje automaticky, tak jako MTA). V důsledku toho explicitně inicializace modelu COM vrací návratové kódy označující, že com je již inicializován. Pokus o explicitní inicializaci modelu COM s jedním modelem vláken, pokud clR již inicializoval model COM do jiného modelu vláken, může způsobit selhání vaší aplikace.
Modul CLR (Common Language Runtime) ve výchozím nastavení spouští model COM jako MTA; k úpravě modelu COM použijte /CLRTHREADATTRIBUTE
(nastavit atribut vlákna CLR).
Problémy s výkonem
Snížení výkonu se může zobrazit, když se nativní metody jazyka C++ vygenerované do jazyka MSIL volají nepřímo (prostřednictvím volání virtuálních funkcí nebo pomocí ukazatelů funkcí). Další informace najdete v tématu Double Thunking.
Když přejdete z nativního prostředí na jazyk MSIL, všimnete si zvýšení velikosti pracovní sady. K tomuto zvýšení dochází, protože modul CLR (Common Language Runtime) poskytuje mnoho funkcí, které zajišťují správné spuštění programů. Pokud vaše /clr
aplikace nefunguje správně, možná budete chtít povolit upozornění kompilátoru mimo výchozí nastavení (úroveň 1 a 3) C4793.
Při vypnutí dojde k chybovému ukončení programu
V některých případech může modul CLR vypnout před dokončením spuštění spravovaného kódu. std::set_terminate
Použití a SIGTERM
může způsobit vypnutí. Další informace naleznete v tématu signal
konstanty a set_terminate
.
Použití nových funkcí jazyka Visual C++
Po kompilaci aplikace, propojení a spuštění můžete začít používat funkce .NET v libovolném modulu zkompilovaném pomocí /clr
. Další informace naleznete v tématu Rozšíření komponent pro platformy modulu runtime.
Další informace o programování v .NET v jazyce Visual C++najdete tady: