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
- Always free the engine when done
- Check return values for NULL/error
- Don’t free message strings - they’re owned by the engine
- 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
- Reuse Engine Instance: Create once, use many times
- Batch Messages: Send multiple before waiting
- Use Thread Pools: For concurrent operations
- Preallocate MCP Servers: Configure all MCPs upfront
- 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.