Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

C/C++ Integration

Native bindings for system programming and embedded applications.


Overview

The C/C++ bindings provide direct access to the Archia engine through a Foreign Function Interface (FFI). This is the foundation for all other language bindings and offers maximum performance with minimal overhead.

Key Features:

  • Zero-overhead FFI interface
  • Thread-safe operations
  • Manual memory management for precise control
  • Compatible with C99 and C++11 or later
  • Header-only integration

Quick Start

Basic Example

#include <archia.h>
#include <stdio.h>

int main() {
    // Initialize engine
    Engine* engine = archia_new();
    if (!engine) {
        fprintf(stderr, "Failed to create engine\n");
        return 1;
    }

    // Create chat session
    size_t chat_id = archia_new_chat(
        engine,
        "You are a helpful assistant",
        NULL, 0,  // No MCP servers
        NULL      // No user data
    );

    // Send message
    Error* err = archia_send(
        engine,
        chat_id,
        "claude-haiku-4-5-20251001",
        "What is the capital of France?"
    );

    if (err) {
        fprintf(stderr, "Error: %s\n", archia_error_message(err));
        archia_error_free(err);
        archia_free(engine);
        return 1;
    }

    // Wait for response
    archia_wait_on(engine, chat_id);

    // Get response
    size_t msg_count = archia_chat_len(engine, chat_id);
    const char* response = archia_chat_message(engine, chat_id, msg_count - 1);
    
    printf("Assistant: %s\n", response);

    // Cleanup
    archia_free(engine);
    return 0;
}

Compilation

# Linux
gcc -o myapp myapp.c -larchia -lpthread

# macOS
clang -o myapp myapp.c -larchia

# Windows (MSVC)
cl myapp.c archia.lib

# Windows (MinGW)
gcc -o myapp.exe myapp.c -larchia -lws2_32

Advanced Usage

With MCP Servers

#include <archia.h>

int main() {
    Engine* engine = archia_new();
    
    // Configure MCP server
    MCPConfig database = {
        .name = "database",
        .cmd = "mcp-sqlite",
        .args = {"production.db", NULL},
        .env = {
            "LOG_LEVEL=info",
            "MAX_CONNECTIONS=10",
            NULL
        }
    };
    
    // Add MCP to engine
    size_t mcp_id = archia_add_mcp(engine, &database);
    
    // Create chat with MCP access
    size_t mcps[] = {mcp_id};
    size_t chat_id = archia_new_chat(
        engine,
        "You are a data analyst with database access",
        mcps, 1,  // 1 MCP server
        NULL
    );
    
    // Query using MCP tools
    archia_send(engine, chat_id, "claude-3-5-sonnet",
        "Show me top 10 customers by revenue");
    
    archia_wait_on(engine, chat_id);
    // ... handle response ...
    
    archia_free(engine);
    return 0;
}

Async Operations

#include <archia.h>
#include <pthread.h>

typedef struct {
    Engine* engine;
    size_t chat_id;
} ThreadData;

void* worker(void* arg) {
    ThreadData* data = (ThreadData*)arg;
    
    // Each thread can send to different chats
    archia_send(data->engine, data->chat_id, 
        "gpt-4", "Process this task...");
    
    archia_wait_on(data->engine, data->chat_id);
    
    // Process response
    size_t len = archia_chat_len(data->engine, data->chat_id);
    const char* result = archia_chat_message(
        data->engine, data->chat_id, len - 1);
    
    printf("Result: %s\n", result);
    return NULL;
}

int main() {
    Engine* engine = archia_new();
    pthread_t threads[4];
    ThreadData thread_data[4];
    
    // Create multiple chat sessions
    for (int i = 0; i < 4; i++) {
        thread_data[i].engine = engine;
        thread_data[i].chat_id = archia_new_chat(
            engine, "Process worker", NULL, 0, NULL);
        
        pthread_create(&threads[i], NULL, worker, &thread_data[i]);
    }
    
    // Wait for all threads
    for (int i = 0; i < 4; i++) {
        pthread_join(threads[i], NULL);
    }
    
    archia_free(engine);
    return 0;
}

Error Handling

Robust error handling example:

#include <archia.h>
#include <stdio.h>

// Helper function for safe operations
int safe_send(Engine* engine, size_t chat_id, 
              const char* model, const char* message) {
    Error* err = archia_send(engine, chat_id, model, message);
    
    if (err) {
        int code = archia_error_code(err);
        const char* msg = archia_error_message(err);
        
        switch (code) {
            case ARCHIA_ERR_INVALID_CHAT:
                fprintf(stderr, "Invalid chat ID: %s\n", msg);
                break;
            case ARCHIA_ERR_MODEL_NOT_FOUND:
                fprintf(stderr, "Model not available: %s\n", msg);
                break;
            case ARCHIA_ERR_API_KEY:
                fprintf(stderr, "API key issue: %s\n", msg);
                break;
            case ARCHIA_ERR_NETWORK:
                fprintf(stderr, "Network error: %s\n", msg);
                break;
            case ARCHIA_ERR_RATE_LIMIT:
                fprintf(stderr, "Rate limit hit: %s\n", msg);
                break;
            default:
                fprintf(stderr, "Error %d: %s\n", code, msg);
        }
        
        archia_error_free(err);
        return -1;
    }
    
    return 0;
}

int main() {
    Engine* engine = archia_new();
    if (!engine) {
        fprintf(stderr, "Failed to initialize\n");
        return 1;
    }
    
    size_t chat = archia_new_chat(engine, "Assistant", NULL, 0, NULL);
    
    // Try sending with error handling
    if (safe_send(engine, chat, "gpt-4", "Hello!") == 0) {
        archia_wait_on(engine, chat);
        // Process response...
    }
    
    archia_free(engine);
    return 0;
}

C++ Wrapper

For C++ projects, use our RAII wrapper for automatic resource management:

#include <archia.hpp>
#include <iostream>

int main() {
    try {
        // RAII - automatic cleanup
        archia::Engine engine;
        
        // Create chat
        auto chat = engine.newChat("You are a C++ expert");
        
        // Send message
        chat.send("claude-3-5-sonnet", 
                  "Write a modern C++20 example");
        
        // Wait and get response
        auto response = chat.waitAndGetResponse();
        std::cout << "Assistant: " << response << std::endl;
        
    } catch (const archia::Error& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
    
    return 0;
}

Error Handling

C Error Handling

Error* err = archia_send(engine, chat_id, model, message);
if (err) {
    const char* msg = archia_error_message(err);
    int code = archia_error_code(err);
    
    switch (code) {
        case ARCHIA_ERR_INVALID_CHAT:
            fprintf(stderr, "Invalid chat ID\n");
            break;
        case ARCHIA_ERR_MODEL_NOT_FOUND:
            fprintf(stderr, "Model not available: %s\n", msg);
            break;
        case ARCHIA_ERR_NETWORK:
            fprintf(stderr, "Network error: %s\n", msg);
            break;
        default:
            fprintf(stderr, "Unknown error: %s\n", msg);
    }
    
    archia_error_free(err);
}

C++ Exception Handling

try {
    engine.send(chat_id, model, message);
} catch (const archia::InvalidChatError& e) {
    // Handle invalid chat
} catch (const archia::ModelError& e) {
    // Handle model issues
} catch (const archia::NetworkError& e) {
    // Handle network problems
} catch (const archia::Error& e) {
    // Generic error handling
}

Memory Management

Best Practices

  1. Always free the engine when done
  2. Check return values for NULL/error
  3. Don’t free message strings - they’re owned by the engine
  4. Free error objects after handling
// Good pattern
Engine* engine = archia_new();
if (!engine) {
    return -1;
}

// Use engine...

// Always cleanup
archia_free(engine);  // This also frees all chats

Performance Tips

  1. Reuse Engine Instance: Create once, use many times
  2. Batch Messages: Send multiple before waiting
  3. Use Thread Pools: For concurrent operations
  4. Preallocate MCP Servers: Configure all MCPs upfront
  5. Stream Responses: Use streaming API for large responses

Platform Notes

Linux

  • Requires glibc 2.17+
  • Links against libpthread automatically

macOS

  • Universal binary (Intel + Apple Silicon)
  • Requires macOS 10.15+

Windows

  • Supports Windows 7+
  • Both MSVC and MinGW toolchains
  • Requires Visual C++ Redistributables

Embedded Systems

  • Supports ARM, RISC-V, MIPS
  • Minimum 4MB RAM
  • Optional NO_STD mode available

Examples

More detailed examples coming soon.