403 lines
7.5 KiB
Markdown
403 lines
7.5 KiB
Markdown
# API Reference
|
||
|
||
Complete reference for the SDL3 header parser command-line interface.
|
||
|
||
## Command Syntax
|
||
|
||
```bash
|
||
zig build run -- <header_file> [options]
|
||
```
|
||
|
||
## Arguments
|
||
|
||
### Required
|
||
|
||
**`<header_file>`** - Path to SDL C header file
|
||
|
||
Examples:
|
||
```bash
|
||
zig build run -- ../SDL/include/SDL3/SDL_gpu.h
|
||
zig build run -- /full/path/to/SDL_video.h
|
||
zig build run -- relative/path/to/header.h
|
||
```
|
||
|
||
### Optional
|
||
|
||
**`--output=<file>`** - Write output to file instead of stdout
|
||
|
||
Examples:
|
||
```bash
|
||
--output=gpu.zig
|
||
--output=bindings/video.zig
|
||
--output=/tmp/test.zig
|
||
```
|
||
|
||
**`--mocks=<file>`** - Generate C mock implementations
|
||
|
||
Examples:
|
||
```bash
|
||
--mocks=gpu_mock.c
|
||
--mocks=test/mocks.c
|
||
```
|
||
|
||
## Output Formats
|
||
|
||
### Zig Bindings (Default)
|
||
|
||
Generated when `--output` is specified (or to stdout if not):
|
||
|
||
```zig
|
||
pub const c = @import("c.zig").c;
|
||
|
||
pub const GPUDevice = opaque {
|
||
pub inline fn createGPUDevice(debug_mode: bool) ?*GPUDevice {
|
||
return c.SDL_CreateGPUDevice(debug_mode);
|
||
}
|
||
};
|
||
```
|
||
|
||
**Features**:
|
||
- Type conversions (C → Zig)
|
||
- Method organization
|
||
- Dependency inclusion
|
||
- Doc comments preserved
|
||
|
||
### C Mocks (Optional)
|
||
|
||
Generated when `--mocks` is specified:
|
||
|
||
```c
|
||
// Auto-generated C mock implementations
|
||
#include <SDL3/SDL_gpu.h>
|
||
|
||
SDL_GPUDevice* SDL_CreateGPUDevice(bool debug_mode) {
|
||
return NULL; // Mock: always returns null
|
||
}
|
||
|
||
void SDL_DestroyGPUDevice(SDL_GPUDevice *device) {
|
||
// Mock: no-op
|
||
}
|
||
```
|
||
|
||
**Use Case**: Testing without real SDL implementation
|
||
|
||
## Build System Integration
|
||
|
||
### In build.zig
|
||
|
||
```zig
|
||
const parser_dep = b.dependency("sdl3_parser", .{
|
||
.target = target,
|
||
.optimize = optimize,
|
||
});
|
||
const parser_exe = parser_dep.artifact("sdl-parser");
|
||
|
||
const gen = b.addRunArtifact(parser_exe);
|
||
gen.addFileArg(b.path("SDL/include/SDL3/SDL_gpu.h"));
|
||
gen.addArg("--output=src/gpu.zig");
|
||
|
||
const gen_step = b.step("generate", "Generate SDL bindings");
|
||
gen_step.dependOn(&gen.step);
|
||
```
|
||
|
||
Then run:
|
||
```bash
|
||
zig build generate
|
||
```
|
||
|
||
## Parser Behavior
|
||
|
||
### Dependency Resolution
|
||
|
||
**Automatic** - No configuration needed
|
||
|
||
When the parser detects missing types, it:
|
||
1. Parses `#include` directives from the header
|
||
2. Searches each included header
|
||
3. Extracts matching type definitions
|
||
4. Includes them in the output
|
||
|
||
**Progress Reporting**:
|
||
```
|
||
Analyzing dependencies...
|
||
Found 5 missing types:
|
||
- SDL_Window
|
||
- SDL_Rect
|
||
...
|
||
|
||
Resolving dependencies...
|
||
✓ Found SDL_Window in SDL_video.h
|
||
✓ Found SDL_Rect in SDL_rect.h
|
||
```
|
||
|
||
### Type Filtering
|
||
|
||
Only SDL types are processed:
|
||
- Types starting with `SDL_`
|
||
- Known SDL types (Window, Rect, etc.)
|
||
|
||
Primitive types are ignored:
|
||
- `bool`, `int`, `float`, `void`, etc.
|
||
|
||
### Pattern Matching Order
|
||
|
||
Patterns are tried in this order:
|
||
1. Opaque types (`typedef struct X X;`)
|
||
2. Enums (`typedef enum {...} X;`)
|
||
3. Structs (`typedef struct {...} X;`)
|
||
4. Flags (`typedef Uint32 SDL_Flags;` + `#define` values)
|
||
5. Typedefs (`typedef Type SDL_Alias;`)
|
||
6. Functions (`extern SDL_DECLSPEC ...`)
|
||
|
||
**Note**: Order matters! Flags must be tried before simple typedefs.
|
||
|
||
### Naming Conventions
|
||
|
||
**Types**:
|
||
- `SDL_GPUDevice` → `GPUDevice` (strip `SDL_` prefix)
|
||
- `SDL_GPU_PRIMITIVE_TYPE` → `GPUPrimitiveType` (remove first underscore)
|
||
|
||
**Functions**:
|
||
- `SDL_CreateGPUDevice` → `createGPUDevice` (strip `SDL_`, camelCase)
|
||
|
||
**Enum Values**:
|
||
- `SDL_GPU_PRIMITIVETYPE_TRIANGLELIST` → `primitiveTypeTrianglelist`
|
||
|
||
**Parameters**:
|
||
- `SDL_GPUDevice *device` → `device: ?*GPUDevice`
|
||
|
||
## Exit Codes
|
||
|
||
- `0` - Success
|
||
- `1` - Error (file not found, out of memory, invalid arguments)
|
||
|
||
## Console Output
|
||
|
||
### Normal Operation
|
||
|
||
```
|
||
SDL3 Header Parser
|
||
==================
|
||
|
||
Parsing: header.h
|
||
|
||
Found N declarations
|
||
- Opaque types: X
|
||
- Typedefs: X
|
||
- Enums: X
|
||
- Structs: X
|
||
- Flags: X
|
||
- Functions: X
|
||
|
||
Analyzing dependencies...
|
||
[dependency information]
|
||
|
||
Generated: output.zig
|
||
```
|
||
|
||
### With Warnings
|
||
|
||
```
|
||
Resolving dependencies...
|
||
✓ Found SDL_Window in SDL_video.h
|
||
⚠ Warning: Could not find definition for type: SDL_Unknown
|
||
```
|
||
|
||
### With Errors
|
||
|
||
```
|
||
Error: 5 syntax errors detected in generated code
|
||
Line 10: expected_comma_after_field
|
||
Line 12: expected_type_expr
|
||
...
|
||
```
|
||
|
||
File is still written, but may need manual fixes.
|
||
|
||
## Type Conversion Reference
|
||
|
||
### Integer Types
|
||
|
||
| C Type | Zig Type |
|
||
|--------|----------|
|
||
| `Uint8` | `u8` |
|
||
| `Uint16` | `u16` |
|
||
| `Uint32` | `u32` |
|
||
| `Uint64` | `u64` |
|
||
| `Sint8` | `i8` |
|
||
| `Sint16` | `i16` |
|
||
| `Sint32` | `i32` |
|
||
| `Sint64` | `i64` |
|
||
| `int` | `c_int` |
|
||
| `unsigned int` | `c_uint` |
|
||
| `size_t` | `usize` |
|
||
|
||
### Pointer Types
|
||
|
||
| C Type | Zig Type |
|
||
|--------|----------|
|
||
| `SDL_Type*` | `?*Type` (nullable) |
|
||
| `const SDL_Type*` | `*const Type` |
|
||
| `SDL_Type**` | `?*?*Type` |
|
||
| `void*` | `?*anyopaque` |
|
||
| `const void*` | `*const anyopaque` |
|
||
| `const char*` | `[*c]const u8` |
|
||
|
||
### Special Types
|
||
|
||
| C Type | Zig Type |
|
||
|--------|----------|
|
||
| `bool` | `bool` |
|
||
| `float` | `f32` |
|
||
| `double` | `f64` |
|
||
| `size_t` | `usize` |
|
||
|
||
## Examples
|
||
|
||
### Example 1: Simple Header
|
||
|
||
**Input** (simple.h):
|
||
```c
|
||
typedef struct SDL_Thing SDL_Thing;
|
||
typedef Uint32 SDL_ThingID;
|
||
|
||
extern SDL_DECLSPEC SDL_ThingID SDLCALL SDL_CreateThing(void);
|
||
extern SDL_DECLSPEC void SDLCALL SDL_DestroyThing(SDL_Thing *thing);
|
||
```
|
||
|
||
**Command**:
|
||
```bash
|
||
zig build run -- simple.h --output=thing.zig
|
||
```
|
||
|
||
**Output** (thing.zig):
|
||
```zig
|
||
pub const c = @import("c.zig").c;
|
||
|
||
pub const ThingID = u32;
|
||
|
||
pub const Thing = opaque {
|
||
pub inline fn destroyThing(thing: *Thing) void {
|
||
return c.SDL_DestroyThing(thing);
|
||
}
|
||
};
|
||
|
||
pub inline fn createThing() ThingID {
|
||
return c.SDL_CreateThing();
|
||
}
|
||
```
|
||
|
||
### Example 2: With Dependencies
|
||
|
||
**Input** (depends.h):
|
||
```c
|
||
#include <SDL3/SDL_rect.h>
|
||
|
||
extern void SDL_UseRect(SDL_Rect *rect);
|
||
```
|
||
|
||
**Command**:
|
||
```bash
|
||
zig build run -- depends.h --output=depends.zig
|
||
```
|
||
|
||
**Output**:
|
||
```zig
|
||
pub const c = @import("c.zig").c;
|
||
|
||
// Dependency automatically included
|
||
pub const Rect = extern struct {
|
||
x: c_int,
|
||
y: c_int,
|
||
w: c_int,
|
||
h: c_int,
|
||
};
|
||
|
||
pub inline fn useRect(rect: *Rect) void {
|
||
return c.SDL_UseRect(rect);
|
||
}
|
||
```
|
||
|
||
### Example 3: With Mocks
|
||
|
||
**Command**:
|
||
```bash
|
||
zig build run -- simple.h --output=thing.zig --mocks=thing_mock.c
|
||
```
|
||
|
||
**Output** (thing_mock.c):
|
||
```c
|
||
#include <SDL3/SDL.h>
|
||
|
||
SDL_ThingID SDL_CreateThing(void) {
|
||
return 0;
|
||
}
|
||
|
||
void SDL_DestroyThing(SDL_Thing *thing) {
|
||
// No-op
|
||
}
|
||
```
|
||
|
||
## Performance Characteristics
|
||
|
||
### Timing
|
||
|
||
| Operation | Time (SDL_gpu.h) |
|
||
|-----------|------------------|
|
||
| Parse primary header | ~50ms |
|
||
| Analyze dependencies | ~10ms |
|
||
| Extract dependencies | ~300ms |
|
||
| Generate code | ~150ms |
|
||
| **Total** | **~520ms** |
|
||
|
||
### Memory
|
||
|
||
| Component | Memory |
|
||
|-----------|--------|
|
||
| Source files | ~150KB |
|
||
| Declarations | ~2MB |
|
||
| Output | ~53KB |
|
||
| **Peak Total** | **~2.2MB** |
|
||
|
||
### Scaling
|
||
|
||
- **Time**: O(n + h×d) where n=lines, h=headers, d=declarations
|
||
- **Memory**: O(d) where d=total declarations
|
||
- **Linear scaling** with input size
|
||
|
||
## Advanced Usage
|
||
|
||
### Batch Processing
|
||
|
||
```bash
|
||
for header in SDL/include/SDL3/SDL_*.h; do
|
||
name=$(basename "$header" .h)
|
||
zig build run -- "$header" --output="bindings/${name}.zig"
|
||
done
|
||
```
|
||
|
||
### CI/CD Integration
|
||
|
||
```yaml
|
||
- name: Generate SDL bindings
|
||
run: |
|
||
cd lib/sdl3
|
||
zig build regenerate-zig
|
||
git diff --exit-code v2/*.zig || echo "Bindings updated"
|
||
```
|
||
|
||
### Validation
|
||
|
||
```bash
|
||
# Generate and validate
|
||
zig build run -- header.h --output=test.zig
|
||
zig ast-check test.zig
|
||
```
|
||
|
||
---
|
||
|
||
**See Also**:
|
||
- [Getting Started](GETTING_STARTED.md) - Basic usage tutorial
|
||
- [Architecture](ARCHITECTURE.md) - How it works internally
|
||
- [Known Issues](KNOWN_ISSUES.md) - Current limitations
|