Di recente mi è capitato, sotto sistema operativo Windows 7, di dover rifare in linguaggio C# una dll realizzata in C++. Come era prevedibile i problemi sono sorti al momento di dover integrare la nuova dll C# in un vecchio progetto C++.
C'è voluta una giornata per venirne a capo.
Premetto che si è lavorato con .NET Framework versione 4.0 e superiori.
Generare la dll C#
Anzitutto realizziamo in Visual Studio.NET la nostra dll C# avendo cura di esporre attraverso una interfaccia i metodi pubblici che vogliamo utilizzare nel nostro progetto C++. Ad es.:
//Dichiarazione di interfaccia
public interface IMessages
{
int printHello(string nome);
};
e l'implementazione del metodo in una classe, ossia:
// Implementazione dell'interfaccia
public class Messages : IMessages
{
public int printHello(string nome)
{
Console.WriteLine("Hello {0} !",nome);
return 0;
}
}
Creiamo un nome sicuro per la dll utilizzando il prompt dei comandi Visual Studio.NET e digitando il seguente comando:
Sn.exe -k MyKeyFile.SNK
Copiare il file MyKeyFile.SNK nella cartella del progetto Visual Studio.NET della dll. Aprire da Visual Studio il file AssemblyInfo.cs del progetto della dll, e sostituire le seguenti stringhe:
[assembly: ComVisible(false)]
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
Con le seguenti:
[assembly: ComVisible(true)]
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("..\\..\\MyKeyFile.SNK")]
dopo di che compiliamo il tutto per generare la dll (supponiamo si chiami Messages.dll).
Integrare la dll C# nel progetto C++
Per utilizzare la dll C# con codice C++ nativo, è necessario registrare le informazioni sull'assembly del file dll nel Registro di sistema. Per far ciò assicuriamoci che sulla macchina dove si trova il progetto C++ sia installato il .NET Framework 4.0 o superiore e individuiamo il percorso del file RegAsm.exe (si trova sotto la cartella del .NET Framework sotto la cartella Windows). Dopo di che copiamo la nostra dll (Messages.dll) sotto la cartella del progetto C++ (si può scegliere una qualsiasi cartella); apriamo il prompt dei comandi, spostiamoci nella cartella del progetto C++ e diamo il seguente comando:
percorsoRegAsm/RegAsm.exe Messages.dll /tlb:Messages.tlb /codebase
sostituiamo percorsoRegAsm con il path individuato in precedenza.
Nota: verificare che la dll appena copiata non risulti bloccata, altrimenti la registrazione non andrà a buon fine.
Andare nelle proprietà del file dll (tasto destro -> proprietà) e verificare che non ci sia il pulsante Sblocca (_Unblock) abilitato.
Aggiungere poi il seguente codice C++ al progetto per richiamare la dll ed i suoi metodi:
#import "..\MessagesDLL.tlb" raw_interfaces_only
using namespace MessagesDll;
sostituire il percorso nell'import, se il file non si trova nella cartella radice del progetto C++. Sostituire nome del file e del namespace con quelli della vostra dll.
// Initialize COM.
HRESULT hr = CoInitialize(NULL);
// Create the interface pointer.
IMessagesPtr pMess(__uuidof(Messages));
BSTR stringa = L"Pietro";
VARIANT_BOOL bResult = false;
// Call the printHello method.
pMess->printHello(stringa, &bResult);
// Uninitialize COM.
CoUninitialize();
That's all. A questo punto dovremmo essere in grado di compilare il progetto C++ con integrata la dll in C#.