Condividi tramite


Procedura: Eseguire la migrazione a /clr

Questo articolo illustra i problemi che si verificano durante la compilazione di codice nativo con /clr. Per altre informazioni, vedere /clr (compilazione Common Language Runtime).) /clr consente al codice C++ nativo di richiamare e essere richiamato da assembly .NET oltre ad altro codice C++ nativo. Per altre informazioni sui vantaggi della compilazione con /clr, vedere Assembly misti (nativi e gestiti) e Interoperabilità nativa e .NET.

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

Visual Studio contiene alcuni problemi noti durante la compilazione di progetti di libreria con /clr:

  • Il codice può eseguire query sui tipi in fase di esecuzione con CRuntimeClass::FromName. Tuttavia, se un tipo si trova in una DLL MSIL (compilata con /clr), la chiamata a FromName potrebbe non riuscire se si verifica prima dell'esecuzione dei costruttori statici nella DLL gestita. Questo problema non verrà visualizzato se la chiamata si verifica dopo l'esecuzione FromName del codice nella DLL gestita. Per risolvere questo problema, è possibile forzare la costruzione del costruttore statico gestito: definire una funzione nella DLL gestita, esportarla e richiamarla dall'applicazione MFC nativa. Ad esempio:

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

Compilare con Visual C++

Prima di usare /clr in qualsiasi modulo del progetto, compilare e collegare il progetto nativo a Visual Studio.

I passaggi seguenti, seguiti nell'ordine, forniscono il percorso più semplice di una /clr compilazione. È importante compilare ed eseguire il progetto dopo ognuno di questi passaggi.

Aggiornamento da versioni precedenti di Visual Studio

Se si esegue l'aggiornamento di Visual Studio da una versione precedente, è possibile che vengano visualizzati errori del compilatore correlati alla conformità C++ Standard avanzata in Visual Studio.

Anche i progetti compilati con versioni precedenti di Visual Studio devono essere compilati senza /clr. Visual Studio ora ha aumentato la conformità C++ Standard e alcune modifiche di rilievo. Le modifiche che potrebbero richiedere la maggior parte dell'attenzione sono funzionalità di sicurezza in CRT. È probabile che il codice che usa CRT generi avvisi di deprecazione. Questi avvisi possono essere eliminati, ma è preferibile eseguire la migrazione alle nuove versioni avanzate della sicurezza delle funzioni CRT, in quanto offrono una maggiore sicurezza e possono rivelare problemi di sicurezza nel codice.

Aggiornamento da Estensioni gestite per C++

In Visual Studio 2005 e versioni successive il codice scritto con Estensioni gestite per C++ non verrà compilato in /clr.

Convertire il codice C in C++

Anche se Visual Studio compilerà i file C, è necessario convertirli in C++ per una /clr compilazione. Il nome file effettivo non deve essere modificato; è possibile usare /Tp (vedere /Tc, /Tp, /TC, /TP (specificare il tipo di file di origine)). Anche se i file di codice sorgente C++ sono necessari per /clr, non è necessario effettuare il refactoring del codice per usare paradigmi orientati agli oggetti.

È probabile che il codice C richieda modifiche durante la compilazione come file C++. Le regole di sicurezza dei tipi C++ sono rigide, quindi 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

I puntatori a funzione sono strettamente indipendenti dai tipi in C++, quindi il codice C seguente richiede modifiche. In C++, è consigliabile creare un oggetto typedef che definisce il tipo di puntatore di funzione e quindi usare 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 anche che le funzioni vengano prototipo o completamente definite prima di poter fare riferimento o richiamare.

Gli identificatori usati nel codice C che si verificano come parole chiave in C++ (ad esempio virtual, deletetruenewbool, , , falsee così via) devono essere rinominati. Questa modifica può essere in genere eseguita con semplici operazioni di ricerca e sostituzione.

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

Riconfigurare le impostazioni del progetto

Dopo la compilazione e l'esecuzione del progetto in Visual Studio, è necessario creare nuove configurazioni di progetto anziché /clr modificare le configurazioni predefinite. /clr non è compatibile con alcune opzioni del compilatore. La creazione di configurazioni separate consente di compilare il progetto come nativo o gestito. Se /clr è selezionata nella finestra di dialogo delle pagine delle proprietà, le impostazioni del progetto non compatibili con /clr sono disabilitate. Le opzioni disabilitate non vengono ripristinate automaticamente se /clr in seguito non è selezionata.

Creare nuove configurazioni di progetto

È possibile usare l'opzione Copia Impostazioni da nella finestra di dialogo Nuova configurazione progetto (Build>Configuration Manager>Active Solution Configuration>New) per creare una configurazione del progetto in base alle impostazioni del progetto esistenti. Creare una copia della configurazione una sola volta per la configurazione di debug e una volta per la configurazione della versione. Le modifiche successive possono quindi essere applicate solo alle /clrconfigurazioni specifiche, lasciando intatte le configurazioni originali del progetto.

I progetti che usano regole di compilazione personalizzate possono richiedere maggiore attenzione.

Questo passaggio ha implicazioni diverse per i progetti che usano makefile. In questo caso, è possibile configurare una destinazione di compilazione separata oppure creare una versione specifica per /clr la compilazione da una copia dell'originale.

Modificare le impostazioni del progetto

/clrpuò essere selezionato nell'ambiente di sviluppo seguendo le istruzioni in /clr (compilazione Common Language Runtime). Come accennato in precedenza, questo passaggio disabiliterà automaticamente le impostazioni del progetto in conflitto.

Nota

Quando si aggiorna un progetto di libreria gestita o di servizio Web da Visual Studio 2003, l'opzione del /Zl compilatore viene aggiunta alla pagina delle proprietà della riga di comando. Ciò causa errori LNK2001. Rimuovere /Zl dalla pagina delle proprietà della riga di comando per risolvere gli errori. Per altre informazioni, vedere /Zl (Omettere il nome della libreria predefinita) e Impostare le proprietà del compilatore e della compilazione.

Per i progetti compilati con makefile, le opzioni del compilatore incompatibili devono essere disabilitate manualmente dopo /clr l'aggiunta. Per informazioni sulle opzioni del compilatore non compatibili con /clr, vedere /clr restrizioni.

Intestazioni precompilate

Le intestazioni precompilate sono supportate in /clr. Tuttavia, se si compilano solo alcuni dei file CPP con /clr (compilando il resto come nativo), sono necessarie alcune modifiche. Le intestazioni precompilate generate con /clr non sono compatibili con le intestazioni precompilate generate senza /clr, perché /clr genera e richiede metadati. I moduli compilati con /clr non possono usare intestazioni precompilate che non includono metadati e/clr non i moduli non possono usare file di intestazione precompilati che contengono metadati.

Il modo più semplice per compilare un progetto in cui alcuni moduli vengono compilati con /clr consiste nel disabilitare completamente le intestazioni precompilate. Nella finestra di dialogo Pagine delle proprietà del progetto aprire Nodo C/C++ e selezionare Intestazioni precompilate. Modificare quindi la proprietà Create/Use Precompiled Headers in "Not Using Precompiled Headers ".)

Tuttavia, in particolare per progetti di grandi dimensioni, le intestazioni precompilate offrono una velocità di compilazione molto migliore, quindi la disabilitazione di questa funzionalità non è consigliabile. In questo caso, è consigliabile configurare i /clr file e non/clr per usare intestazioni precompilate separate. È possibile configurarli in un unico passaggio: selezionare più moduli con /clr cui eseguire la compilazione usando Esplora soluzioni. Fare clic con il pulsante destro del mouse sul gruppo e scegliere Proprietà. Modificare quindi entrambe le proprietà Create/Use PCH Through File e Precompilato Header File per usare rispettivamente un nome di file di intestazione diverso e un file PCH.

Correggere gli errori

La compilazione del codice con /clr può comportare errori del compilatore, del linker o del runtime. In questa sezione vengono illustrati i problemi più comuni.

Unione dei metadati

Le versioni diverse dei tipi di dati possono causare l'esito negativo del linker perché i metadati generati per i due tipi non corrispondono. Gli errori si verificano quando si definiscono in modo condizionale i membri di un tipo, ma le condizioni non sono uguali per tutti i file CPP che usano il tipo. In questo caso, il linker ha esito negativo, segnalando solo il nome del simbolo e il nome del secondo file OBJ in cui è stato definito il tipo. Può risultare utile ruotare l'ordine in cui i file OBJ vengono inviati al linker per individuare il percorso dell'altra versione del tipo di dati.

Deadlock del blocco del caricatore

Il "deadlock del blocco del caricatore" può verificarsi, ma è deterministico e viene rilevato e segnalato in fase di esecuzione. Per informazioni dettagliate, indicazioni e soluzioni, vedere Inizializzazione di assembly misti.

Esportazioni dati

L'esportazione di dati DLL è soggetta a errori e non è consigliata nel /clr codice. Perché l'inizializzazione della sezione dei dati di una DLL non è garantita fino a quando non viene eseguita una parte gestita della DLL. Fare riferimento ai metadati con #using direttive.

Visibilità dei tipi

I tipi nativi sono private per impostazione predefinita. Un private tipo nativo non è visibile all'esterno della DLL. Risolvere questo errore aggiungendo public a questi tipi.

Problemi di allineamento e virgola mobile

__controlfp non è supportato in Common Language Runtime. Per altre informazioni, vedere , , _controlfp__control87_2._control87 CLR non rispetta alignanche .

Inizializzazione COM

Common Language Runtime inizializza automaticamente COM quando un modulo viene inizializzato (quando COM viene inizializzato automaticamente, come MTA). Di conseguenza, l'inizializzazione esplicita di COM restituisce codici restituiti che indicano che COM è già inizializzato. Il tentativo di inizializzare in modo esplicito COM con un modello di threading quando CLR ha già inizializzato COM in un altro modello di threading può causare un errore dell'applicazione.

Common Language Runtime avvia COM come MTA per impostazione predefinita; usare /CLRTHREADATTRIBUTE (Impostare l'attributo del thread CLR) per modificare il modello COM.

Problemi di prestazioni

È possibile che vengano visualizzate prestazioni ridotte quando i metodi C++ nativi generati in MSIL vengono chiamati indirettamente (tramite chiamate di funzione virtuali o tramite puntatori a funzione). Per altre informazioni, vedere Double Thunking.

Quando si passa da nativo a MSIL, si noterà un aumento delle dimensioni del working set. Questo aumento si verifica perché Common Language Runtime offre molte funzionalità per garantire che i programmi vengano eseguiti correttamente. Se l'applicazione /clr non è in esecuzione correttamente, potrebbe essere necessario abilitare l'avviso del compilatore disattivato (livello 1 e 3) C4793.

Arresto anomalo del programma all'arresto

In alcuni casi, CLR può essere arrestato prima del completamento dell'esecuzione del codice gestito. L'uso di std::set_terminate e SIGTERM può causare l'arresto. Per altre informazioni, vedere signal costanti e set_terminate.

Uso delle nuove funzionalità di Visual C++

Dopo la compilazione, i collegamenti e l'esecuzione dell'applicazione, è possibile iniziare a usare le funzionalità .NET in qualsiasi modulo compilato con /clr. Per altre informazioni, vedere Component Extensions for Runtime Platforms.

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

Vedi anche

Assembly misti (nativi e gestiti)