Introducción: Por qué GraphQL y C++ son una combinación poderosa
GraphQL se ha convertido en un estándar para APIs modernas, ofreciendo flexibilidad y eficiencia en comparación con REST. Pero, ¿cómo implementarlo en C++, un lenguaje conocido por su rendimiento y rigor? En este tutorial, analizaremos la creación de una API GraphQL completa en C++ utilizando la biblioteca cppgraphqlgen. Aprenderá a definir un esquema, escribir resolvers, procesar consultas y mutaciones. Los ejemplos de código serán prácticos para que pueda aplicarlos inmediatamente en sus proyectos.
Al final del artículo, podrá crear un servidor GraphQL simple pero funcional en C++ que acepte consultas y devuelva datos. ¡Comencemos!
Instalación y configuración del entorno
Para trabajar necesitaremos:
- Un compilador compatible con C++17 (por ejemplo, GCC 8+ o Clang 7+)
- CMake (versión 3.14+)
- La biblioteca
cppgraphqlgen(generación de código a partir del esquema GraphQL) - Un servidor HTTP (por ejemplo,
cpp-httplibpara simplicidad)
Instalaremos las dependencias a través de vcpkg o las compilaremos manualmente. Para este tutorial usamos vcpkg:
git clone https://github.com/Microsoft/vcpkg.gitcd vcpkg./bootstrap-vcpkg.sh./vcpkg install cppgraphqlgen cpp-httplibCrearemos la estructura del proyecto:
graphql-cpp-tutorial/├── schema.graphql├── CMakeLists.txt├── src/│ ├── main.cpp│ ├── resolver.cpp│ └── resolver.hPaso 1: Definimos el esquema GraphQL
Crearemos el archivo schema.graphql con un esquema simple para gestionar tareas (Todo):
type Query { todos: [Todo!]! todo(id: ID!): Todo}
type Mutation { addTodo(title: String!): Todo! completeTodo(id: ID!): Todo}
type Todo { id: ID! title: String! completed: Boolean!}Este esquema describe:
- Query — obtener una lista de tareas o una tarea por ID
- Mutation — agregar una nueva tarea y marcar como completada
- Type Todo — un objeto con los campos id, title, completed
El esquema es el contrato de nuestra API. A continuación, generaremos el código C++ a partir de él.
Paso 2: Generación de código C++ a partir del esquema
Usaremos la utilidad graphqlgenerategen del paquete cppgraphqlgen:
graphqlgenerategen schema.graphql --output-dir ./generatedDespués de la ejecución, en la carpeta generated aparecerán los archivos:
TodoObject.h— clase para el tipo TodoQueryObject.h— clase base para los resolvers de QueryMutationObject.h— clase base para los resolvers de Mutationschema.h— integración del esquema
Estos archivos contienen las interfaces generadas que debemos implementar.
Paso 3: Implementación de los resolvers
Crearemos el archivo resolver.h con las declaraciones:
#include "generated/QueryObject.h"#include "generated/MutationObject.h"#include <vector>#include <memory>
struct Todo { std::string id; std::string title; bool completed;};
class QueryResolver : public graphql::todo::QueryObject {public: std::vector<std::shared_ptr<graphql::todo::TodoObject>> getTodos() const override; std::shared_ptr<graphql::todo::TodoObject> getTodo(const std::string& id) const override;
private: static std::vector<Todo> todos_;};
class MutationResolver : public graphql::todo::MutationObject {public: std::shared_ptr<graphql::todo::TodoObject> applyAddTodo(const std::string& title) override; std::shared_ptr<graphql::todo::TodoObject> applyCompleteTodo(const std::string& id) override;};Ahora implementaremos la lógica en resolver.cpp:
#include "