Condividi tramite


Procedura: eseguire la migrazione a /clr

In questo argomento vengono analizzati i problemi derivanti durante la compilazione di codice nativo con /clr (per ulteriori informazioni, vedere /clr (Compilazione Common Language Runtime))./clr consente ai moduli Visual C++ di richiamare ed essere richiamati dagli assembly .NET durante il mantenimento di compatibilità con i moduli non gestiti.Per ulteriori informazioni sui vantaggi offerti dalla compilazione con /clr, vedere Assembly misti (nativi e gestiti) e Interoperabilità .NET e nativa.

Problemi noti relativi alla compilazione di progetti di librerie con /clr

Visual Studio presenta alcuni problemi noti durante la compilazione di progetti di librerie con /clr:

  • Il codice può eseguire query nei tipi in fase di esecuzione con CRuntimeClass::FromName.Tuttavia, se un tipo è incluso in un file con estensione dll MSIL (compilato con /clr), la chiamata a CRuntimeClass::FromName potrebbe avere esito negativo se si verifica prima dei costruttori statici eseguiti nel file con estensione dll gestito (questo problema non si verifica se la chiamata a FromName si verifica dopo che il codice è stato eseguito nel file con estensione dll gestito).Per aggirare questo problema è possibile imporre la costruzione del costruttore statico gestito definendo una funzione nel file con estensione dll gestito, esportandolo e richiamandolo dall'applicazione MFC nativa.Di seguito è riportato un esempio:

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

Eseguire la compilazione con Visual C++

Prima di utilizzare /clr su un qualsiasi modulo del progetto, compilare e collegare il progetto nativo tramite Visual Studio 2010.

I passaggi riportati di seguito, da eseguire nell'ordine indicato, rappresentano la procedura più semplice per una compilazione con /clr.È importante che il progetto venga compilato ed eseguito dopo ognuno di questi passaggi.

ms173265.collapse_all(it-it,VS.110).gifVersioni precedenti a Visual C++ 2003

Se si esegue l'aggiornamento in Visual Studio 2010 da una versione precedente a Visual C++ 2003, è possibile riscontrare errori del compilatore connessi alla conformità standard C++ avanzata di Visual C++ 2003.

ms173265.collapse_all(it-it,VS.110).gifAggiornamento da Visual C++ 2003

È consigliabile che i progetti compilati in precedenza con Visual C++ 2003 vengano inizialmente compilati senza /clr, poiché in Visual Studio ora è stata incrementata la conformità agli standard ANSI/ISO e sono state introdotte alcune modifiche che possono determinare interruzioni.La modifica che sembra richiedere maggiore attenzione è illustrata nell'argomento Funzionalità di sicurezza in CRT.È estremamente probabile che il codice che utilizza CRT produca avvisi negativi.Sebbene sia possibile eliminare tali avvisi, è tuttavia preferibile eseguire una migrazione alle nuove Versioni con sicurezza Avanzate di funzioni CRT, che sono in grado di fornire una maggiore sicurezza e di individuare problemi di sicurezza all'interno del codice.

ms173265.collapse_all(it-it,VS.110).gifAggiornamento dalle estensioni gestite per C++

I progetti compilati con Visual C++ .NET o Visual C++ 2003 che hanno utilizzato le estensioni gestite per C++ richiederanno almeno una modifica alle impostazioni di progetto, poiché tali estensioni sono ormai deprecate.Di conseguenza, il codice scritto con le estensioni gestite per C++ non verrà compilato in /clr.In alternativa, utilizzare /clr:oldSyntax.

Convertire codice C in C++

Sebbene Visual Studio sia in grado di compilare file C, è necessario convertirli in C++ per una compilazione /clr.La modifica del nome file effettivo non è richiesta; è possibile utilizzare /Tp (vedere /Tc, /Tp, /TC, /TP (Specifica il tipo di file di origine)). Nonostante /clr richieda i file di codice sorgente C++, non è tuttavia necessario effettuare il refactoring del codice per utilizzare paradigmi orientati a oggetti.

È estremamente probabile che il codice C richieda modifiche se compilato come file C++.Le regole di indipendenza dai tipi C++ sono rigorose, pertanto le conversioni dei tipi devono essere rese esplicite con i cast.Ad esempio, malloc restituisce un puntatore void, ma può essere assegnato a un puntatore a qualsiasi tipo in C con un cast:

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

Anche i puntatori a funzione sono rigorosamente indipendenti dai tipi in C++ e quindi il codice C riportato di seguito richiede alcune modifiche.In C++ è consigliabile creare un typedef che definisca il tipo di puntatore a funzione e quindi utilizzare tale tipo per eseguire il cast dei puntatori a funzione:

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

C++ richiede inoltre che tali funzioni siano con prototipo o completamente definite per potervi fare riferimento o per essere richiamate.

Gli identificatori utilizzati nel codice C che risultano essere parole chiave in C++ (ad esempio virtual, new, delete, bool, true, false e così via) devono essere rinominati.Per eseguire questa operazione, è generalmente sufficiente eseguire semplici operazioni di ricerca e sostituzione.

Infine, mentre le chiamate COM di tipo C richiedono l'utilizzo esplicito di v-table e del puntatore this, in C++ questi non risultano necessari:

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

Riconfigurare le impostazioni del progetto

Dopo aver compilato ed eseguito il progetto in Visual Studio 2010 è consigliabile creare nuove configurazioni di progetto per /clr piuttosto che modificare le configurazioni predefinite./clr è incompatibile con alcune opzioni del compilatore e la creazione di configurazioni separate consente di compilare il progetto come nativo o gestito.Quando si seleziona /clr nella finestra di dialogo delle pagine delle proprietà, le impostazioni del progetto non compatibili con /clr vengono disabilitate (e il ripristino delle opzioni disabilitate non avviene automaticamente quando si deseleziona /clr in un secondo momento).

ms173265.collapse_all(it-it,VS.110).gifCreare nuove configurazioni del progetto

È possibile utilizzare l'opzione Copia impostazioni da della Finestra di dialogo Nuova configurazione progetto per creare una configurazione del progetto basata sulle relative impostazioni esistenti.Questa operazione deve essere eseguita una volta per la configurazione per il debug e una per la configurazione per il rilascio.Le modifiche successive possono quindi essere applicate esclusivamente alle configurazioni specifiche di /clr, lasciando inalterate quelle originali relative al progetto.

I progetti che utilizzano regole di compilazione personalizzate potrebbero richiedere particolare attenzione.

Questo passaggio presenta implicazioni diverse per i progetti che utilizzano i makefile.In questo caso è possibile configurare una destinazione di generazione separata o creare una versione specifica della compilazione /clr a partire da una copia dell'originale.

ms173265.collapse_all(it-it,VS.110).gifModificare le impostazioni del progetto

Per selezionare /clr nell'ambiente di sviluppo, è sufficiente seguire le istruzioni fornite in /clr (Compilazione Common Language Runtime).Come accennato in precedenza, questo passaggio consente di disabilitare automaticamente le impostazioni di progetto in conflitto.

[!NOTA]

Quando si aggiorna una libreria gestita o un progetto di servizi Web da Visual C++ 2003, l'opzione del compilatore /Zl viene aggiunta alla pagina delle proprietà Riga di comando.Ciò determina l'errore LNK2001.Per risolverlo, rimuovere /Zl dalla pagina delle proprietà Riga di comando.Per ulteriori informazioni, vedere /Zl (Omette il nome della libreria predefinita) e Procedura: aprire le pagine delle proprietà dei progetti.In alternativa, aggiungere msvcrt.lib e msvcmrt.lib alla proprietà Dipendenze aggiuntive del linker.

Nei progetti creati con makefile, le opzioni non compatibili del compilatore devono essere disabilitate manualmente dopo aver aggiunto /clr.Per informazioni sulle opzioni del compilatore non compatibili con /clr, vedere /Limitazioni di /clr.

ms173265.collapse_all(it-it,VS.110).gifIntestazioni precompilate

Le intestazioni precompilate sono supportate in /clr.Tuttavia, se si compilano alcuni dei file CPP con /clr e i restanti come nativi, sarà necessario apportare determinate modifiche, poiché le intestazioni precompilate generate con /clr non sono compatibili con quelle generate senza /clr.Tale incompatibilità è dovuta al fatto che /clr genera e richiede metadati.I moduli /clr compilati non possono quindi utilizzare intestazioni precompilate che non includono metadati e i moduli non /clr non possono utilizzare file di intestazione precompilati che contengono metadati.

Il modo più semplice per compilare un progetto in cui alcuni moduli sono /clr compilati consiste nel disabilitare completamente le intestazioni precompilate(nella finestra di dialogo Pagine delle proprietà del progetto aprire il nodo C/C++ e selezionare Intestazioni precompilate,quindi modificare la proprietà Crea/usa intestazioni precompilate in "Senza intestazioni precompilate").

Tuttavia, soprattutto per quanto riguarda i progetti di grandi dimensioni, le intestazioni precompilate garantiscono una più elevata velocità di compilazione e pertanto disabilitare questa funzionalità non è sempre consigliabile.In questo caso la soluzione migliore consiste nel configurare i file /clr e non /clr in modo da utilizzare intestazioni precompilate separate.Questo risultato può essere ottenuto con un unico passaggio, selezionando i moduli /clr da compilare in Esplora soluzioni, facendo clic con il pulsante destro del mouse sul gruppo e scegliendo Proprietà.A questo punto modificare entrambe le proprietà "Crea/Usa PCH tramite file" e "File di intestazione precompilato" in modo da ricorrere a un diverso nome del file di intestazione e a un altro file PCH, rispettivamente.

Correzione degli errori

La compilazione con /clr potrebbe provocare errori del compilatore, del linker o di runtime.In questa sezione vengono illustrati i problemi più comuni.

ms173265.collapse_all(it-it,VS.110).gifUnione di metadati

Versioni diverse dei tipi di dati possono causare errori del linker dovuti al fatto che i metadati generati per i due tipi non corrispondono(questo si verifica, in genere, quando i membri di un tipo vengono definiti in base a determinate condizioni, che tuttavia non sono le stesse per tutti i file CPP che utilizzano il tipo). Questo provoca un errore del linker, che segnala solo il nome del simbolo e il nome del secondo file OBJ in cui il tipo è stato definito.Spesso risulta utile alternare l'ordine di invio dei file OBJ al linker in modo da individuare la posizione dell'altra versione del tipo di dati.

ms173265.collapse_all(it-it,VS.110).gifDeadlock del blocco del caricatore

In Visual C++ .NET e Visual C++ 2003, l'inizializzazione in /clr era suscettibile di deadlock non deterministico.Il problema è noto come "deadlock del blocco del caricatore".In Visual Studio 2010, il deadlock è più semplice da evitare, viene rilevato e segnalato al momento del runtime e non è più non deterministico.Riscontrare il problema del blocco del caricatore è ancora possibile, ma ora risulta più facile evitarlo e risolverlo.Per informazioni dettagliate, istruzioni e soluzioni, vedere Inizializzazione di assembly misti.

ms173265.collapse_all(it-it,VS.110).gifEsportazioni di dati

L'esportazione di dati DLL è suscettibile di errori e non è pertanto consigliabile.Questo si verifica perché non esiste alcuna garanzia che la sezione di dati di una DLL venga inizializzata fino a quando una parte gestita della DLL stessa risulta completamente eseguita.Per fare riferimento ai metadati, utilizzare la direttiva #using (C++).

ms173265.collapse_all(it-it,VS.110).gifVisibilità del tipo

I tipi nativi sono ora privati per impostazione predefinita,mentre in Visual C++ .NET 2002 e Visual C++ 2003 erano pubblici.Per questo motivo, un tipo nativo potrebbe non risultare visibile al di fuori della DLL.L'errore può essere risolto aggiungendo public a tali tipi.Per ulteriori informazioni, vedere Visibilità di tipi e membri.

ms173265.collapse_all(it-it,VS.110).gifProblemi di allineamento e virgola mobile

__controlfp non è supportato in Common Language Runtime (per ulteriori informazioni, vedere _control87, _controlfp, __control87_2).CLR non rispetta inoltre align (C++).

ms173265.collapse_all(it-it,VS.110).gifInizializzazione COM

Common Language Runtime inizializza COM automaticamente quando viene inizializzato un modulo (l'inizializzazione automatica di COM ne comporta la trasformazione in MTA).Di conseguenza, l'inizializzazione esplicita di COM genera codici restituiti a indicare che COM è già stato inizializzato.Se si tenta di inizializzare COM in modo esplicito con un modello di threading quando CLR lo ha già inizializzato con un altro modello di threading, può verificarsi l'arresto dell'applicazione.

Common Language Runtime avvia COM come MTA per impostazione predefinita. Per modificare questa situazione, utilizzare /CLRTHREADATTRIBUTE (Imposta l'attributo thread CLR).

ms173265.collapse_all(it-it,VS.110).gifProblemi relativi alle prestazioni

Le prestazioni potrebbero registrare un peggioramento quando i metodi C++ nativi generati per MSIL vengono chiamati indirettamente (chiamate di funzione virtuale o utilizzo di puntatori a funzione).Per ulteriori informazioni, vedere Doppio thunk (C++).

Nel passaggio dal formato nativo a MSIL, è possibile che le dimensioni del working set aumentino.Questo si verifica perché il Common Language Runtime fornisce numerose funzionalità che consentono di garantire la corretta esecuzione del programma.Se l'applicazione /clr non viene eseguita correttamente, è possibile attivare C4793 (disattivato per impostazione predefinita). Per ulteriori informazioni, vedere Avviso del compilatore (livelli 1 e 3) C4793.

ms173265.collapse_all(it-it,VS.110).gifArresti anomali al momento della chiusura

In alcuni casi CLR potrebbe chiudersi prima che il codice gestito abbia completato l'esecuzione.Questo problema può verificarsi quando si utilizzano std::set_terminate e SIGTERM.Per ulteriori informazioni, vedere costanti del segnale e set_terminate (<exception>).

Utilizzo di nuove funzionalità Visual C++

Quando l'applicazione risulta compilata, collegata ed eseguita, è possibile iniziare a utilizzare le funzionalità .NET in qualsiasi modulo compilato con /clr.Per ulteriori informazioni, vedere Estensioni componenti per le piattaforme runtime.

Se sono state applicate le estensioni gestite per C++, è possibile convertire il codice in modo da utilizzare la nuova sintassi.Per un riepilogo delle differenze sintattiche, vedere Managed Extensions for C++ Syntax Upgrade Checklist.Per informazioni dettagliate sulla conversione delle estensioni gestite per C++, vedere Nozioni di base della migrazione in C++/CLI.

Per informazioni sulla programmazione .NET in Visual C++, vedere:

Vedere anche

Concetti

Assembly misti (nativi e gestiti)