Esempio pratico di un ponte COM per chiamare una DLL a 64 bit da un'applicazione a 32 bit

· Aggiornato il: · · COM, Sviluppo Windows, 32 bit, 64 bit

Cronologia delle revisioni (prima versione, pubblicata il 25 Jan 2026)
Prima pubblicazione
Citare questo articolo(DOI: 10.5281/zenodo.22170262)

Questo articolo è archiviato su Zenodo. Qui sotto trovi sia il DOI che rimanda sempre all'ultima versione sia quello fissato alla versione che stai leggendo.

Go Komura (2026). Esempio pratico di un ponte COM per chiamare una DLL a 64 bit da un'applicazione a 32 bit. KomuraSoft LLC. https://doi.org/10.5281/zenodo.22170262 https://comcomponent.com/it/blog/2026/01/25/002-com-case-study-32bit-to-64bit/

DOI (ultima versione)
10.5281/zenodo.22170262
DOI (questa versione)
10.5281/zenodo.22170263

Volere chiamare una DLL a 64 bit da un’applicazione a 32 bit è un’esigenza abbastanza comune su Windows. Soprattutto quando si vogliono mantenere in sede asset esistenti e usare solo la funzionalità del lato a 64 bit, un’architettura a ponte COM tende a essere la risposta pratica.

Indice

  1. Lo scenario
  2. La soluzione
  3. Flusso di elaborazione (diagramma di sequenza)
  4. Codice di esempio (concettuale)
  5. Codice di esempio completo
  6. Riferimenti

1. Lo scenario

Questo è il caso in cui si vuole mantenere un’applicazione a 32 bit così com’è, ma usare un’elaborazione che risiede in una DLL a 64 bit. Il problema è che un processo a 32 bit non può caricare una DLL a 64 bit. È un vincolo a livello di sistema operativo: non si può aggirare con trucchi.

La situazione tipica è questa.

  • L’applicazione a 32 bit esistente è un asset di grandi dimensioni e non può essere migrata a breve
  • La DLL a 64 bit ha nuove funzionalità, oppure le sue dipendenze sono solo a 64 bit
  • Si vuole chiamarla dal lato a 32 bit “con i tipi”

Con questa combinazione, la strada in-process è chiusa fin dall’inizio.

2. La soluzione

La soluzione di base è separare tramite COM out-of-process (un server EXE). La DLL a 64 bit viene chiamata da un server COM a 64 bit (EXE), e l’applicazione a 32 bit la utilizza tramite COM.

Il flusso è il seguente.

  1. Costruire un COM LocalServer a 64 bit (EXE) che chiama internamente la DLL a 64 bit
  2. Condividere l’interfaccia COM (IDL/TypeLib) per esporre i tipi
  3. L’applicazione a 32 bit chiama COM “con i tipi” (comunicando tramite proxy/marshaling)

Ci sono comunque delle avvertenze.

  • Le registrazioni a 32 bit e a 64 bit sono separate (incluso WOW6432Node)
  • Le strutture personalizzate richiedono una progettazione di marshaling
  • Esiste un overhead IPC, quindi fare attenzione alle chiamate ad alta frequenza

In sintesi, l’approccio collaudato è “spostare l’elaborazione a 64 bit in un processo separato e collegarla con COM”.

Se poi ciò che si vuole usare sul lato a 64 bit è già di per sé un server COM in-process (una DLL registrata tramite InprocServer32), può capitare di non dover scrivere alcun server EXE. Assegnando un AppID al CLSID e scrivendo in quella chiave AppID un DllSurrogate con valore stringa vuota, quella DLL viene ospitata nel processo surrogato fornito con Windows (per una DLL a 64 bit, System32\dllhost.exe) e dal client a 32 bit appare come un server COM out-of-process che gira in un processo separato (non si tratta di registrare il percorso di un EXE in LocalServer32; anzi, se LocalServer32 è presente il surrogato non viene usato). Anche nella direzione opposta (usare una DLL COM a 32 bit da un’applicazione a 64 bit) il meccanismo è lo stesso, e la bitness del surrogato che viene avviato è determinata dal lato della DLL, non dal client. Tuttavia, se come in questo articolo ciò che si vuole chiamare è una semplice DLL nativa, non esiste alcun server COM da ospitare nel surrogato, quindi serve l’approccio con server EXE descritto nel seguito. La procedura di registrazione è riassunta nel 3.5 di Registration and Bitness Pitfalls in COM/OCX/ActiveX Development (là si presuppone una DLL a 32 bit, quindi basta reinterpretare la view in cui si scrive il valore AppID), mentre il criterio per stabilire se basta il surrogato o se occorre scrivere un EXE proprio è riassunto nel 5.2 di Come gestire ActiveX / OCX oggi - Una tabella decisionale Mantieni / Avvolgi / Sostituisci.

3. Flusso di elaborazione (diagramma di sequenza)

Di seguito il flusso quando l’applicazione a 32 bit invoca l’elaborazione nella DLL a 64 bit.

Gestito dall'infrastruttura di marshaling COM registrataDLL 64 bitServer COM 64 bit(EXE)Stub COM(lato 64 bit)RPC/IPC(comunicazione inter-processo)Proxy COM(lato 32 bit)App client 32 bitDLL 64 bitServer COM 64 bit(EXE)Stub COM(lato 64 bit)RPC/IPC(comunicazione inter-processo)Proxy COM(lato 32 bit)App client 32 bitEsegue il marshaling dei parametriEsegue l'unmarshaling dei parametriEsegue il marshaling del valore di ritornoEsegue l'unmarshaling del valore di ritornoICalcService.Add(1, 2)Dati serializzatiTrasferiti attraverso il confine di processoAdd(1, 2)Chiamata a funzione nativaRisultato: 3Risultato: 3Risultato serializzatoTrasferito attraverso il confine di processoRisultato: 3

Punti chiave:

  • L’applicazione a 32 bit può effettuare chiamate type-safe attraverso l’interfaccia ICalcService
  • Il runtime COM attraversa il confine di processo usando la DLL proxy/stub registrata, il marshaler della libreria dei tipi, il marshaler standard e così via
  • A causa dell’overhead della comunicazione inter-processo, è preferibile raggruppare il lavoro anziché fare molte chiamate a grana fine

4. Codice di esempio (concettuale)

Di seguito uno schizzo concettuale. In pratica servono anche registrazione, generazione della TypeLib e così via.

// Interfaccia condivisa (equivalente IDL)
[ComVisible(true)]
[Guid("7A4B5B23-0A2F-4D2B-9D4D-8A2A92B8B001")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ICalcService
{
    int Add(int a, int b);
}

// COM LocalServer a 64 bit (lato EXE)
[ComVisible(true)]
[Guid("1C9B6F4D-1E9A-4E61-9A4F-6A0F1D2D9A11")]
[ClassInterface(ClassInterfaceType.None)]
public class CalcService : ICalcService
{
    public int Add(int a, int b)
    {
        // Qui viene chiamata la DLL a 64 bit
        return a + b;
    }
}

// Lato app a 32 bit (client)
Type t = Type.GetTypeFromProgID("KomuraSoft.CalcService");
var calc = (ICalcService)Activator.CreateInstance(t);
int result = calc.Add(1, 2);

Con questa forma, il lato a 32 bit può lavorare “con i tipi”. COM usa proxy/stub internamente ed effettua la chiamata su IPC per noi.

5. Codice di esempio completo

Un’implementazione funzionante del concetto sopra è pubblicata su GitHub.

Call64bitDLLFrom32bitProc - GitHub

Il repository contiene quanto segue:

  • Call64bitDLLFrom32bitProc/ - COM LocalServer a 64 bit (EXE)
  • X64DLL/ - DLL a 64 bit (l’elaborazione effettiva)
  • X86App/ - Client a 32 bit (WinForms)
  • scripts/ - Script di registrazione/deregistrazione del server COM

Se lo si compila e registra seguendo i passaggi del README, si può vedere un processo a 32 bit che chiama effettivamente una DLL a 64 bit.

6. Riferimenti

  • Component Object Model (COM) overview https://learn.microsoft.com/en-us/windows/win32/com/component-object-model–com–portal
  • COM LocalServer32 registration https://learn.microsoft.com/en-us/windows/win32/com/localserver32
  • COM interface basics https://learn.microsoft.com/en-us/windows/win32/com/the-component-object-model
  • COM Interop (use from .NET) https://learn.microsoft.com/en-us/dotnet/standard/native-interop/cominterop

Articoli recenti con gli stessi tag per approfondire argomenti vicini.

Queste pagine collocano l’argomento in un contesto più ampio di servizi e decisioni.

L’articolo è direttamente collegato ai servizi seguenti.

Domande frequenti

Domande che ricorrono nelle consulenze sull’argomento dell’articolo.

Un'applicazione a 32 bit può caricare una DLL a 64 bit?
No. Un processo a 32 bit non può caricare una DLL a 64 bit: è un vincolo a livello di sistema operativo su Windows, non qualcosa che si possa aggirare con trucchi. La strada in-process è chiusa fin dall'inizio. Se serve la funzionalità che risiede in una DLL a 64 bit, l'elaborazione deve essere eseguita in un processo separato a 64 bit, e un ponte COM è un modo collaudato per collegare i due.
Come collega un ponte COM un'applicazione a 32 bit a una DLL a 64 bit?
Si costruisce un COM LocalServer a 64 bit (un EXE) che chiama internamente la DLL a 64 bit, si condivide l'interfaccia COM tramite IDL o una libreria dei tipi per esporre i tipi, e l'applicazione a 32 bit la utilizza attraverso COM. Il runtime COM attraversa il confine dei processi usando proxy, stub e marshaling, quindi il lato a 32 bit può effettuare chiamate type-safe attraverso l'interfaccia condivisa.
Quali sono i principali avvertenze quando si usa un ponte COM out-of-process?
Ce ne sono tre principali. Primo, le registrazioni COM a 32 bit e a 64 bit sono separate, inclusa l'area di registro WOW6432Node. Secondo, le strutture personalizzate richiedono una progettazione di marshaling anziché funzionare automaticamente. Terzo, la comunicazione inter-processo aggiunge overhead a ogni chiamata, quindi è preferibile raggruppare il lavoro anziché fare molte chiamate a grana fine in scenari ad alta frequenza.
Esiste un esempio funzionante di ponte COM da 32 a 64 bit?
Sì. Un'implementazione completa e funzionante è pubblicata su GitHub come repository Call64bitDLLFrom32bitProc. Contiene un COM LocalServer a 64 bit (EXE), una DLL a 64 bit con l'elaborazione effettiva, un client WinForms a 32 bit e script di registrazione del server COM. Se lo si compila e registra seguendo il README, si può vedere un processo a 32 bit che chiama effettivamente una DLL a 64 bit.

Profilo dell’autore

Pagina di presentazione dell’autore dell’articolo.

Go Komura

Rappresentante di KomuraSoft LLC

Specializzato nello sviluppo di software Windows, nella consulenza tecnica e nell’analisi dei malfunzionamenti, soprattutto nei progetti con sistemi esistenti e guasti difficili da riprodurre.

Torna al blog