Interoperabilidad Swift-C++ en 2026: llamar a C++ desde Swift de forma nativa

Swift siempre tuvo interoperabilidad con C y Objective-C. Llamar a funciones C desde Swift es directo y automático; con Objective-C el compilador genera los puentes necesarios sin intervención manual. Pero C++ ha sido históricamente el agujero negro: la única forma de usarlo desde Swift era envolverlo en un shim de C u Objective-C++. Eso cambió con Swift 5.9, que introdujo interoperabilidad directa Swift-C++ como característica experimental, y que en 2026 está lo suficientemente madura para uso en producción en muchos casos.

Por qué importa la interop con C++

El ecosistema Apple tiene enormes cantidades de código C++: motores de juegos (Metal, RealityKit internamente), librerías de visión artificial, procesamiento de señal, engines de audio, SDKs de terceros. Antes de Swift 5.9, integrar cualquiera de esas librerías requería una capa de Objective-C++ que añadía complejidad y fricción. Con la interop nativa, puedes llamar directamente a clases, funciones y templates de C++ desde Swift.

Activar la interoperabilidad C++

La interop C++ se activa por módulo. En Swift Package Manager:

// Package.swift
targets: [
    .target(
        name: "MiTarget",
        swiftSettings: [
            .interoperabilityMode(.Cxx)
        ]
    )
]

En Xcode, en la configuración del target: Swift Compiler - Language > C++ and Objective-C Interoperability ? C++ / Objective-C++.

Usar código C++ desde Swift

Supongamos que tienes una librería C++ con esta cabecera:

// MathLib.h (C++)
#pragma once
#include <cstdint>
#include <vector>

namespace MathLib {
    struct Vector3 {
        float x, y, z;
        float length() const;
        Vector3 normalized() const;
        Vector3 operator+(const Vector3& other) const;
    };

    std::vector<int32_t> primos(int32_t hasta);
}

Con la interop activada, desde Swift puedes usar esto directamente:

import MathLib

// Usar el struct C++
var v1 = MathLib.Vector3(x: 1, y: 2, z: 3)
var v2 = MathLib.Vector3(x: 4, y: 5, z: 6)

// Operaciones (el operador + se mapea automáticamente)
let suma = v1 + v2
let longitud = v1.length()
let normalizado = v1.normalized()

// std::vector se convierte a secuencia iterable
let listaPrimos = MathLib.primos(100)
for primo in listaPrimos {
    print(primo)
}

Qué se soporta y qué no

La interop cubre una parte significativa de C++ moderno, pero no todo:

Soportado:

  • Structs y clases de C++ como tipos de valor y referencia.
  • Funciones libres y métodos miembro (incluyendo const).
  • Namespaces (se mapean como enums sin casos en Swift).
  • std::vector, std::string, std::map como tipos iterables.
  • Templates con tipos concretos (instanciación en el lado C++).
  • Herencia de clases C++ (acceso a métodos de la clase base).

Con limitaciones o no soportado:

  • Templates con tipos Swift (no se puede instanciar un template C++ con un tipo Swift).
  • Herencia virtual compleja con múltiples niveles.
  • Excepciones C++ (se convierten en abort o se deben manejar en el lado C++).
  • Algunos tipos de la STL con semántica especial.

Llamar a Swift desde C++

La interop funciona en ambas direcciones. Los tipos Swift marcados con @_expose(Cxx) pueden usarse desde código C++:

// Swift
@_expose(Cxx)
public struct Punto {
    public var x: Double
    public var y: Double

    public init(x: Double, y: Double) {
        self.x = x
        self.y = y
    }

    public func distanciaAlOrigen() -> Double {
        (x * x + y * y).squareRoot()
    }
}
// C++ (usando el header generado)
#include "MiModuloSwift-Swift.h"

auto punto = MiModuloSwift::Punto(3.0, 4.0);
double dist = punto.distanciaAlOrigen(); // 5.0

Casos de uso prácticos en 2026

Los escenarios donde esta interop brilla en proyectos reales son:

  • Motores de física y geometría: librerías como Bullet Physics, Open3D o eigen están en C++. Llamarlas directamente desde Swift sin wrapper.
  • SDKs de machine learning: algunas librerías de inferencia de ML (ONNX Runtime, por ejemplo) tienen APIs C++.
  • Migración gradual: proyectos que mezclan C++ legacy con Swift nuevo pueden migrar por módulos sin reescribir todo de golpe.
  • Juegos con Godot o similar: los bindings de Swift para engines C++ se benefician enormemente de esta interop.

Para proyectos que también necesitan interoperabilidad con C++ desde otros lenguajes modernos, la serie sobre Rust y su interop con C/C++ ofrece una perspectiva diferente: Rust también puede llamar a C++ pero mediante un modelo de FFI más explícito, sin la integración a nivel de compilador que Swift ofrece desde 5.9.

Imagen: Pexels / Daniil Komov

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP