Esempio pratico di un ponte COM per chiamare una DLL a 64 bit da un'applicazione a 32 bit
· Aggiornato il: · Go Komura · COM, Sviluppo Windows, 32 bit, 64 bit
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
- Lo scenario
- La soluzione
- Flusso di elaborazione (diagramma di sequenza)
- Codice di esempio (concettuale)
- Codice di esempio completo
- 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.
- Costruire un COM LocalServer a 64 bit (EXE) che chiama internamente la DLL a 64 bit
- Condividere l’interfaccia COM (IDL/TypeLib) per esporre i tipi
- 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”.
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.
sequenceDiagram
participant App as App client 32 bit
box rgba(100,100,255,0.1) Gestito dall'infrastruttura di marshaling COM registrata
participant Proxy as Proxy COM<br/>(lato 32 bit)
participant RPC as RPC/IPC<br/>(comunicazione inter-processo)
participant Stub as Stub COM<br/>(lato 64 bit)
end
participant Server as Server COM 64 bit<br/>(EXE)
participant DLL as DLL 64 bit
App->>Proxy: ICalcService.Add(1, 2)
rect rgba(100,100,255,0.1)
Note over Proxy: Esegue il marshaling dei parametri
Proxy->>RPC: Dati serializzati
RPC->>Stub: Trasferiti attraverso il confine di processo
Note over Stub: Esegue l'unmarshaling dei parametri
end
Stub->>Server: Add(1, 2)
Server->>DLL: Chiamata a funzione nativa
DLL-->>Server: Risultato: 3
Server-->>Stub: Risultato: 3
rect rgba(100,100,255,0.1)
Note over Stub: Esegue il marshaling del valore di ritorno
Stub-->>RPC: Risultato serializzato
RPC-->>Proxy: Trasferito attraverso il confine di processo
Note over Proxy: Esegue l'unmarshaling del valore di ritorno
end
Proxy-->>App: Risultato: 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 correlati
Articoli recenti con gli stessi tag per approfondire argomenti vicini.
Fino a quando funzioneranno le applicazioni VB6? — Lo stato del supporto al runtime e un percorso pratico verso la migrazione a .NET
Fino a quando continueranno a funzionare le applicazioni VB6? Questo articolo chiarisce l'asimmetria tra la politica di supporto del runt...
Outsourcing e sviluppo su commissione di app Windows: cosa chiarire prima di affidare l'incarico
Prima di affidare in outsourcing o su commissione lo sviluppo di un'app Windows, ecco i punti da chiarire: revisione del software esisten...
Il curioso amore di uno sviluppatore, ovvero: come ho imparato a non preoccuparmi e ad amare Windows
Windows è complicato. Ma questa complicazione è anche quella di un sistema operativo che da decenni porta sulle spalle il lavoro reale.
Cos'è Reg-Free COM - Utilizzo di COM senza registrazione
Una panoramica delle basi di Reg-Free COM, i ruoli dei contesti di attivazione e dei manifest, i vantaggi, le limitazioni e come decidere...
Come costruire l'output di report Excel - COM / Open XML / Template
La progettazione dell'output di report Excel cambia considerevolmente a seconda che si automatizzi Excel stesso, si generino file xlsx di...
Argomenti correlati
Queste pagine collocano l’argomento in un contesto più ampio di servizi e decisioni.
Argomenti tecnici Windows
Portale su sviluppo Windows, analisi dei problemi e valorizzazione delle risorse esistenti.
Migrazione ActiveX
Scelte per mantenere, incapsulare o sostituire componenti COM / ActiveX / OCX.
Servizi collegati all’argomento
L’articolo è direttamente collegato ai servizi seguenti.
Riutilizzo e migrazione delle risorse esistenti
Si tratta di costruire un ponte verso il lato a 64 bit mantenendo in sede gli asset a 32 bit, rientra direttamente nel supporto alla riutilizzazione e migrazione di asset legacy.
Consulenza tecnica e revisione del progetto
Se si vuole prima chiarire la progettazione del ponte COM o dove tracciare i confini dei processi, possiamo confrontare le opzioni insieme attraverso consulenza tecnica e design review.
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.