rawlib

package
v0.18.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 24, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package rawlib contains the per-construct emitters that convert [meta] structures into the raw CGo library Go source files and bridge files.

Each top-level function writes one logical output unit:

  • [Classes] — one .go file per ObjC class, using struct embedding to model the superclass chain.
  • [ClassInterfaces] — one <Name>able Go interface per ObjC class, enabling mock implementations for testing and polymorphic acceptance.
  • [Bridge] — a C header (.h) and Objective-C implementation (.m) with thin wrapper functions for every bridged method. Bridge files are compiled with -fno-objc-arc; returned objects are +1 retained.
  • [Enums] — typed Go const blocks; bitmask enums receive a bitwise String method.
  • [Structs] — value-type wrappers for C structs (CGRect, CGSize, etc.).
  • [Protocols] — Go interface types for ObjC @protocols.
  • [Externs] — package-level constants for extern symbols.
  • [Functions] — Go wrappers for free C functions.
  • [Blocks] — named Go func types for ObjC block signatures.
  • [BlockTrampolines] — CGo trampoline header and implementation.
  • [ForeignExtensions] — package-level functions for ObjC categories that extend a class owned by a different framework.
  • [FoundationVariadicWrappers] — hand-authored Go variadic overloads for Foundation methods whose ObjC signature is variadic.

Emitters discover their import requirements as a side effect of type resolution: they populate a usedImports map during body generation, then write the file header (with import block) followed by the body in a single pass.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BlockSigName

func BlockSigName(objcType string, m *typemap.Mapper) string

BlockSigName returns the canonical C-safe name for an ObjC block type string. Two ObjC block types that share the same primitive C representation produce the same name (e.g. "void (^)(id)" and "void (^)(NSError *)" both → "void_ptr"). Returns "" when the block type cannot be parsed.

func EmitBSDPackage

func EmitBSDPackage(w io.Writer) error

EmitBSDPackage writes the static bsd support package source. The type mapper resolves POSIX/BSD C structs (see typemap's bsdStructTypes) to bsd.TypeName references, so the package must exist alongside the generated C library packages. Because the libraries output tree is wiped on every run, the package is re-emitted by the generator rather than hand-crafted.

func EmitBlocks

func EmitBlocks(w io.Writer, framework *macosplatformmetadata.FrameworkMeta, m *typemap.Mapper, knownClasses map[string]bool) error

EmitBlocks writes named Go func types for each unique ObjC block signature collected by the scanner.

func EmitBridge

func EmitBridge(outDir string, framework *macosplatformmetadata.FrameworkMeta, m *typemap.Mapper, knownClasses map[string]bool) error

Bridge generates the C bridge header (.h) and ObjC implementation (.m) for a framework, writing both into outDir/bridge/, plus a thin shim .m file in outDir (the package root) that #includes the bridge implementation so that CGo auto-compiles it. (CGo only auto-compiles .m files in the package root, not in subdirectories.)

Why we generate C bridge functions rather than calling ObjC methods directly:

CGo only understands C calling conventions — it cannot express Objective-C message sends ([object method]) at all. The ObjC methods already exist on macOS, compiled into the framework dylibs, but the only way Go can invoke them is through a plain C function. Each generated bridge function:

  1. Accepts CGo-compatible parameters (void* for ObjC objects, scalar types)
  2. Casts them back to ObjC types and sends the message
  3. Retains the result with [retain] before returning (see memory model below)
  4. Returns a C-compatible value

No method logic is reimplemented; the bridge is purely a calling-convention adapter. The alternative — using objc_msgSend directly — is fragile: the cast of the function pointer varies by return type and architecture. The generated wrapper approach is far more robust.

Memory model for returned ObjC objects (non-ARC):

All bridge .m files are compiled with -fno-objc-arc. In non-ARC code, __bridge_retained is a no-op (equivalent to __bridge). Returned ObjC objects would be autoreleased by the @autoreleasepool block and freed before the Go caller could use them. To match Go's finalizer model, every bridge function that returns an ObjC object calls [_result retain] before returning. The Go wrapper calls runtime.Track to register a CFRelease finalizer, which releases that +1 retain when the Go GC collects the wrapper.

Why some methods are skipped (marked Unavailable in metadata):

A small number of SDK classes mark their -init and +new methods with __attribute__((unavailable)) / NS_UNAVAILABLE. This is a hard Clang compile-time error, not a runtime version guard. These are factory-only classes (e.g. NSCollectionLayoutDimension, WKWebExtensionAction) where Apple's design explicitly forbids bare initialisation; callers must use the class factory methods. Generating call sites for unavailable methods would produce code that does not compile. Skipping them honours the SDK's explicit design intent.

func EmitBridgeHeader

func EmitBridgeHeader(w io.Writer, framework *macosplatformmetadata.FrameworkMeta, m *typemap.Mapper, knownClasses map[string]bool) error

BridgeHeader writes the C bridge header (.h) to w.

func EmitBridgeImpl

func EmitBridgeImpl(w io.Writer, framework *macosplatformmetadata.FrameworkMeta, m *typemap.Mapper, knownClasses map[string]bool, headerName string) error

BridgeImpl writes the ObjC bridge implementation (.m) to w.

func EmitClass

func EmitClass(
	w io.Writer,
	name string,
	cls macosplatformmetadata.Class,
	framework *macosplatformmetadata.FrameworkMeta,
	m *typemap.Mapper,
	knownClasses map[string]bool,
	allClasses map[string]macosplatformmetadata.Class,
	packageName string,
) error

WriteClass writes a single ObjC class as a Go source file using struct embedding for inheritance. Root classes (no superclass or unknown superclass) retain a plain `ptr unsafe.Pointer` field. Non-root classes embed their immediate superclass by value; Go's method promotion gives access to all ancestor methods.

func EmitClassInterfaces

func EmitClassInterfaces(w io.Writer, pkgName string, framework *macosplatformmetadata.FrameworkMeta, m *typemap.Mapper, knownClasses map[string]bool, allClasses map[string]macosplatformmetadata.Class) error

EmitClassInterfaces writes one [ClassName]able interface per concrete ObjC class, modelled on the Kiota [Type]able pattern. Each interface lists all instance methods with identical signatures to those emitted on *ClassName, enabling mock implementations for testing and polymorphic acceptance of compatible types.

Generic classes (e.g. NSArray[T]) are skipped in this pass — their interface signatures require type parameters that complicate the embedding chain.

func EmitClasses

func EmitClasses(
	outDir string,
	framework *macosplatformmetadata.FrameworkMeta,
	m *typemap.Mapper,
	knownClasses map[string]bool,
	allClasses map[string]macosplatformmetadata.Class,
	packageName string,
) error

Classes writes one Go source file per ObjC class into outDir. allClasses is the combined class map from all frameworks, used for building cross-framework embedding chains and constructors.

func EmitEnums

func EmitEnums(w io.Writer, framework *macosplatformmetadata.FrameworkMeta) error

Enums writes all enum types and their constants to w.

func EmitExterns

func EmitExterns(w io.Writer, pkgName string, framework *macosplatformmetadata.FrameworkMeta, m *typemap.Mapper, knownClasses map[string]bool) error

Externs writes a complete _externs.go file for the framework's extern symbols.

func EmitFoundationVariadicWrappers

func EmitFoundationVariadicWrappers(w io.Writer, pkgName string) error

EmitFoundationVariadicWrappers writes convenience variadic constructors for the most commonly used Foundation collection classes (NSArray, NSMutableArray, NSSet, NSMutableSet, NSDictionary, NSMutableDictionary). The underlying ObjC nil-terminated variadics (+arrayWithObjects:, +dictionaryWithObjectsAndKeys:, etc.) are not bridgeable via CGo; these wrappers use either:

  • A pure-Go path via existing non-variadic bridged methods (NSArray, NSSet),
  • An embedded C helper (non-variadic wrapper) per the CGo pattern for functions that have no suitable non-variadic ObjC equivalent (NSDictionary).

The generated file is written only for the Foundation framework.

func EmitFunctions

func EmitFunctions(w io.Writer, pkgName, packageName string, framework *macosplatformmetadata.FrameworkMeta, m *typemap.Mapper, knownClasses map[string]bool) error

Functions writes a complete _functions.go file for the framework's plain C functions.

func EmitGeneratedBridgesImpl

func EmitGeneratedBridgesImpl(outDir, packageName string) error

EmitGeneratedBridgesImpl writes {packageName}_impl.m at outDir — a CGo-compiled aggregate that #includes all *_subclass.m and *_impl.m files from bridge/. Without this file the ObjC symbols defined in those bridge files would not be linked. If no generated bridge files exist the file is not written.

func EmitProtocolImpls

func EmitProtocolImpls(outDir string, framework *macosplatformmetadata.FrameworkMeta, m *typemap.Mapper) error

EmitProtocolImpls writes per-protocol callback files for all protocols in framework.

For each protocol NSFooDelegate it writes:

  • outDir/NSFooDelegate_protocol_callback.go — NSFooDelegateCallbacks struct + NewNSFooDelegateProtocolCallback
  • outDir/bridge/NSFooDelegate_protocol_callback.h
  • outDir/bridge/NSFooDelegate_protocol_callback.m

func EmitProtocolProxies

func EmitProtocolProxies(
	w io.Writer,
	pkgName, packageName string,
	framework *macosplatformmetadata.FrameworkMeta,
	m *typemap.Mapper,
	knownClasses map[string]bool,
	allClasses map[string]macosplatformmetadata.Class,
) error

ProtocolProxies writes a Go source file containing concrete id<Protocol> wrapper types for each ObjC protocol in the framework that appears in a return position.

The name reflects the ObjC id<Protocol> concept: each type is named <GoProtoName>IDProtocol (e.g. VZVirtualMachineDelegateIDProtocol for id<VZVirtualMachineDelegate>). The type:

  • Embeds foundation.NSObject, satisfying cgo.Object and NSObjectProtocol
  • Exports a New<Name> constructor that registers a GC finalizer via cgo.Track
  • Implements all non-variadic protocol methods via CGo bridge calls that cast the receiver to id<Protocol> and dispatch dynamically

func EmitProtocols

func EmitProtocols(w io.Writer, pkgName string, framework *macosplatformmetadata.FrameworkMeta, m *typemap.Mapper, knownClasses map[string]bool, knownProtocols map[string]string, allClasses map[string]macosplatformmetadata.Class) error

Protocols writes a complete _protocols.go file with Go interface definitions for all ObjC protocols in the framework.

func EmitRuntimeBlocksGo

func EmitRuntimeBlocksGo(w io.Writer, sigs []BlockSignatureModel, pkg string) error

EmitRuntimeBlocksGo writes the generated runtime/blocks_generated.go file. This file contains //export goCallBlock_* callbacks and MakeBlock_* factories.

func EmitRuntimeBlocksTrampolineHeader

func EmitRuntimeBlocksTrampolineHeader(w io.Writer, sigs []BlockSignatureModel) error

EmitRuntimeBlocksTrampolineHeader writes runtime/block_trampolines_generated.h.

func EmitRuntimeBlocksTrampolineImpl

func EmitRuntimeBlocksTrampolineImpl(w io.Writer, sigs []BlockSignatureModel) error

EmitRuntimeBlocksTrampolineImpl writes runtime/block_trampolines_generated.m.

func EmitRuntimeCallbacksGo

func EmitRuntimeCallbacksGo(w io.Writer, sigs []MethodSigModel, pkg string) error

EmitRuntimeCallbacksGo writes callbacks_generated.go for the bindings/runtime/callbacks package.

func EmitRuntimeCallbacksTrampolineHeader

func EmitRuntimeCallbacksTrampolineHeader(w io.Writer, sigs []MethodSigModel) error

EmitRuntimeCallbacksTrampolineHeader writes method_trampolines_generated.h.

func EmitRuntimeCallbacksTrampolineImpl

func EmitRuntimeCallbacksTrampolineImpl(w io.Writer, sigs []MethodSigModel) error

EmitRuntimeCallbacksTrampolineImpl writes method_trampolines_generated.m.

func EmitStructs

func EmitStructs(w io.Writer, framework *macosplatformmetadata.FrameworkMeta, m *typemap.Mapper, knownClasses map[string]bool) (typemap.ImportSet, error)

Structs writes all C struct type definitions and struct typedef aliases to w. It returns a map of Go package alias → import path for any cross-framework imports required by struct fields (e.g. corefoundation for CF-typed fields).

func EmitSubclassFactories

func EmitSubclassFactories(outDir string, framework *macosplatformmetadata.FrameworkMeta, m *typemap.Mapper, superIndex map[string]bool, allClasses map[string]macosplatformmetadata.Class) error

EmitSubclassFactories writes per-class subclass factory files for all classes in framework that appear in superIndex (i.e. classes that Apple itself subclasses).

For each eligible class NSFoo it writes:

  • outDir/NSFoo_subclass.go — NSFooOverrides struct + NewNSFooSubclass factory
  • outDir/bridge/NSFoo_subclass.h — C declarations
  • outDir/bridge/NSFoo_subclass.m — ObjC alloc+class_addMethod+BindCallback

func EmittableFunctions

func EmittableFunctions(framework *macosplatformmetadata.FrameworkMeta) []macosplatformmetadata.Function

EmittableFunctions returns the plain C functions that EmitFunctions emits as Go wrappers for framework, in declaration order, after applying the same skip and de-duplication rules (inline/variadic/unavailable/builtin/UPP/va_list/by-value unknown filters, plus collision with package-level type names). The idiomatic library layer uses this so it only ever wraps raw functions that actually exist.

func EnumsNeedImports

func EnumsNeedImports(framework *macosplatformmetadata.FrameworkMeta) (needsFmt, needsStrings bool)

EnumsNeedImports reports which stdlib imports the enum file will need.

func FunctionGoName added in v0.15.0

FunctionGoName returns the Go wrapper name EmitFunctions gives fn. C permits a struct and a function to share a name (e.g. mach_time.h declares both a mach_timebase_info struct and function); the natural Go name then collides with the emitted type, so the wrapper gains an "Fn" suffix (Mach_timebase_infoFn) instead of being silently dropped. The idiomatic layer resolves its raw call targets through this same rule.

Types

type BlockSigArg

type BlockSigArg struct {
	CType   string // C type in the trampoline: "void *", "int64_t", "bool"
	CGOType string // CGo type in the //export function: "unsafe.Pointer", "C.int64_t"
	GoType  string // Go type in MakeBlock factory: "unsafe.Pointer", "int64", "bool"
}

BlockSigArg describes a single argument in a BlockSignatureModel.

type BlockSignatureModel

type BlockSignatureModel struct {
	Name      string // canonical C-safe name: "void_ptr_ptr", "int64_ptr_ptr"
	IsVoidRet bool   // true when block returns void
	RetC      string // C return type: "int64_t", "bool", "" for void
	RetCGo    string // CGo type in //export: "C.int64_t", "C.bool", "" for void
	RetGo     string // Go return type: "int64", "bool", "" for void
	Args      []BlockSigArg
}

BlockSignatureModel describes a unique primitive-typed block signature. Two ObjC block types that differ only in ObjC object types (e.g. id vs NSString *) produce the same BlockSignatureModel because they share the same C/Go representation.

func BlockSigFromObjC

func BlockSigFromObjC(objcType string, m *typemap.Mapper) (BlockSignatureModel, bool)

BlockSigFromObjC builds a BlockSignatureModel from an ObjC block type string. Returns the zero value and false if the type cannot be parsed.

func CollectBlockSignaturesFromFrameworks

func CollectBlockSignaturesFromFrameworks(frameworks []*macosplatformmetadata.FrameworkMeta, m *typemap.Mapper) []BlockSignatureModel

CollectBlockSignaturesFromFrameworks scans all methods/protocols/extensions in the provided list of framework metas and returns the deduplicated, sorted set of BlockSignatures that need Go trampolines.

type MethodSigArg

type MethodSigArg struct {
	CType   string // C type in the trampoline: "void *", "int64_t", "bool"
	CGOType string // CGo type in the //export function
	GoType  string // Go type in the callback func
	Enc     string // ObjC type encoding character(s)
}

MethodSigArg describes one explicit argument (not self or _cmd).

type MethodSigModel

type MethodSigModel struct {
	Name          string // "void_ptr_ptr" — retToken[_argToken...]  (no self token)
	IsVoidRet     bool
	CReturnType   string // C return type: "void", "int64_t", "bool"
	CGoReturnType string // CGo type: "C.int64_t", "C.bool", "" for void
	GoReturnType  string // Go return type: "int64", "bool", "" for void
	Params        []MethodSigArg
	ObjCEnc       string // ObjC type encoding for class_addMethod: "v@:@"
}

MethodSigModel describes a unique primitive-typed IMP method signature. Two ObjC methods that differ only in ObjC object types share the same MethodSigModel because they use the same C/Go representation.

Unlike block signatures, self (id) is always implicit — it is NOT reflected in the Name tokens. The Go callback ALWAYS receives self as its first arg.

func CollectMethodSigsFromFrameworks

func CollectMethodSigsFromFrameworks(frameworks []*macosplatformmetadata.FrameworkMeta, m *typemap.Mapper) []MethodSigModel

CollectMethodSigsFromFrameworks scans all class and protocol methods in frameworks and returns the deduplicated, sorted set of MethodSigs that need IMP trampolines. Methods with struct-by-value arguments/returns are excluded (not IMP-safe).

Directories

Path Synopsis
Package render executes the raw CGo library templates.
Package render executes the raw CGo library templates.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL