Calling a 64-bit DLL from a 32-bit App - A COM Bridge Case Study

· · COM, Windows Development, 32-bit, 64-bit

what’s the problem

you want to keep your existing 32-bit application but use logic that lives in a 64-bit DLL.

The hard constraint: a 32-bit process cannot load a 64-bit DLL. This is enforced at the Windows OS level. There’s no way to make the call inside a single process.

Typical situations:

  • the existing 32-bit app is large and can’t be migrated to 64-bit any time soon
  • the new features only ship in the 64-bit build of the library
  • you want to call into it type-safely from the 32-bit side

the solution: a COM bridge

The core idea is simple — push the 64-bit work into a separate process and bridge it with COM.

Architecture

[32-bit app] -> [COM Proxy] -> [RPC/IPC] -> [COM Stub] -> [64-bit COM server (EXE)] -> [64-bit DLL]

How it works

  1. Build a 64-bit COM LocalServer (an EXE) that loads and calls the 64-bit DLL.
  2. Share a COM interface (IDL/TypeLib) so both sides see the same types.
  3. The 32-bit app calls through COM with full type information.

Things to watch out for

  • 32-bit and 64-bit COM registrations are separate — mind WOW6432Node
  • if you pass custom structs, you’ll need to design the marshaling
  • there’s IPC overhead on every call, so batch the work instead of chattering across the boundary

Call flow (sequence)

32-bit client app
    | ICalcService.Add(1, 2)  -- type-safe COM call
    v
COM Proxy (32-bit side)
    | serialize parameters
    v
RPC/IPC (cross-process)
    | transfer across the process boundary
    v
COM Stub (64-bit side)
    | rehydrate parameters
    v
64-bit COM Server (EXE)
    | invoke native function
    v
64-bit DLL
    | run the computation
    v
result travels back the same way

Sample code (C#)

Shared interface

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

64-bit COM server implementation

[ComVisible(true)]
[Guid("1C9B6F4D-1E9A-4E61-9A4F-6A0F1D2D9A11")]
[ClassInterface(ClassInterfaceType.None)]
public class CalcService : ICalcService
{
    public int Add(int a, int b)
    {
        // Call the native function inside the 64-bit DLL
        return NativeDll.Add(a, b);
    }
}

Calling from the 32-bit app

Type t = Type.GetTypeFromProgID("KomuraSoft.CalcService");
var calc = (ICalcService)Activator.CreateInstance(t);
int result = calc.Add(1, 2);  // result: 3

The 32-bit side talks to ICalcService type-safely. COM transparently handles the Proxy/Stub plumbing and ferries the call across IPC for you.

Full sample

A working sample is up on GitHub.

Call64bitDLLFrom32bitProc - GitHub

What’s in it:

  • Call64bitDLLFrom32bitProc/ — the 64-bit COM LocalServer (EXE)
  • X64DLL/ — the 64-bit DLL that does the real work
  • X86App/ — the 32-bit client app (WinForms)
  • scripts/ — register/unregister scripts for the COM server

Wrap-up

  • calling a 64-bit DLL directly from a 32-bit app is impossible at the OS level
  • with out-of-proc COM, the 64-bit work lives in its own process
  • COM handles Proxy/Stub marshaling for you
  • watch out for IPC overhead on hot paths
  • in practice, design a batched API rather than fine-grained calls

References

Related Articles

Recent articles sharing the same tags. Deepen your understanding with closely related topics.

Related Topics

These topic pages place the article in a broader service and decision context.

Where This Topic Connects

This article connects naturally to the following service pages.

Back to the Blog