c-for-go

repository·master·Indexed 23 days ago

https://github.com/xlab/c-for-go

An automatic C-Go bindings generator that allows developers to reuse existing C/C++ libraries in Go applications. It uses a YAML manifest to define parsing and translation rules, automating the creation of low-level cgo bindings by interpreting C headers and generating corresponding Go code.

Tokens
1.3K
Snippets
1
Records
9
Agent score
82%

What's inside c-for-go

  1. How c-for-go works

    master

    c-for-go automates the creation of cgo bindings for C/C++ libraries.

    The Workflow:

    1. Manifest File: You provide a YAML manifest file that defines rules for parsing, translation, and generation.
    2. Parsing & Translation: The tool uses the manifest to interpret C headers and translate them into Go-compatible structures.
    3. Code Generation: It generates Go code that wraps the source C/C++ code.

    Key Characteristics:

    • Low-level Bindings: The generated bindings are as low-level as the original C code. Users must manage memory carefully when using them.
    • Manual Wrappers: While the tool generates the low-level bindings, it is common practice to manually write high-level Go wrappers on top of them to implement Object-Oriented Design, manage state, and improve memory safety.
  2. How the Process lifecycle works

    master

    The Process manages a multi-stage pipeline to convert C headers into Go bindings. The typical lifecycle is:

    1. Setup: Call NewProcess with a YAML config. This prepares the parser, translator, and generator.
    2. Execution: Call Generate(noCGO). This populates internal memory buffers with the generated source code.
    3. Finalization: Call Flush(noCGO). This closes the generator, waits for background helper generation to finish, and writes the buffers to files in the specified outputPath.

    Internal Buffers: To support modular Go packages, the process uses different buffers for different types of code:

    • BufDoc: doc.go (Documentation)
    • BufConst: const.go (Constants)
    • BufTypes: types.go (Typedefs)
    • BufUnions: unions.go (Unions)
    • BufHelpers: cgo_helpers.go (Go helpers)
    • BufMain: The main package file (e.g., pkgname.go)
  3. Generate Go and C bindings using Process.Generate

    master

    The Generate(noCGO bool) method orchestrates the writing of code into internal buffers. It follows a specific order to ensure dependencies are met:

    1. Package Header & Docs: Writes the package documentation and header.
    2. Includes: If noCGO is false, writes necessary C includes.
    3. Constants: Writes constant definitions (either to a dedicated const.go buffer or the main buffer).
    4. Types: Writes typedefs and type definitions.
    5. Unions & Declares: If noCGO is false, writes unions and declarations.

    Note: This method does not write to disk; it only populates the internal buffers.

  4. Write generated files to disk with Process.Flush

    master

    The Flush(noCGO bool) method finalizes the generation by writing all populated buffers to the filesystem.

    Behavior:

    • It creates the output directory if it doesn't exist.
    • It writes Go files based on the goBufferNames mapping (e.g., doc.go, const.go, types.go, unions.go, cgo_helpers.go).
    • If noCGO is false, it also writes cgo_helpers.h and cgo_helpers.c.
    • Go files are automatically processed with goimports to ensure correct imports and formatting.
    • If noCGO is true, C helper files are skipped.

    Parameters:

    • noCGO (bool): If true, skips generating CGO-related files (includes, unions, and C helper files).
  5. Initialize a binding generation workflow with NewProcess

    master

    To start the C-to-Go binding generation process, use NewProcess(configPath, outputPath). This function performs the following steps:

    1. Loads and unmarshals a YAML configuration file into a ProcessConfig.
    2. Configures the Parser using pkg-config options if provided in the generator config.
    3. Parses the C headers using the parser package.
    4. Initializes the translator and teaches it the C model (ABI, types, etc.).
    5. Initializes the generator with the parsed model and configuration.
    6. Sets up internal buffers for different Go file components (docs, constants, types, unions, helpers).

    Returns a pointer to a Process instance or an error if configuration loading, parsing, or translation fails.

  6. c-for-go CLI flags reference

    master

    The following flags control the behavior of the c-for-go generator:

    • -out string: Specify a directory for the output files.
    • -nocgo: Do not include a cgo-specific header in the resulting files.
    • -ccdefs: Use built-in defines from a hosted C-compiler.
    • -ccincl: Use built-in sys include paths from a hosted C-compiler.
    • -maxmem string: Specifies the platform's memory cap for the generated code (default: 0x7fffffff).
    • -fancy: Enable fancy output in the terminal (default: true).
    • -nostamp: Disable printing timestamps in the output files.
    • -debug: Enable debug information.
  7. Use the c-for-go CLI

    master
    The c-for-go command is used to generate Go code from C package configuration files (YAML). You can provide one or more configuration file paths or directories as arguments. If a directory is provided, the tool looks for c-for-go.yaml or c-for-go.yml within that directory.
  8. Define binding generation configuration with ProcessConfig

    master

    The ProcessConfig struct defines the configuration for the entire generation pipeline. It is designed to be unmarshaled from a YAML file. It contains sub-configurations for the three main stages of the pipeline:

    • Generator: Configuration for the code generation engine (*generator.Config).
    • Translator: Configuration for the C-to-Go type translation logic (*translator.Config).
    • Parser: Configuration for the C header parsing stage (*parser.Config).