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::mapcomo 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
