Overview
The InteropGenerator is an incremental source generator that:- Processes structs marked with
[GenerateInterop] - Generates P/Invoke-style method implementations
- Creates address resolution code for signature scanning
- Generates convenient accessors for fixed-size arrays and bitfields
- Handles struct inheritance and virtual tables
- Produces string overloads for C-string parameters
How It Works
1. Struct Discovery
The generator uses Roslyn’sForAttributeWithMetadataName to find all structs decorated with [GenerateInterop]:
2. Code Generation
For each struct, the generator creates a partial class file:{StructName}.InteropGenerator.g.cs
Input:
Generated Components
Struct Size Constant
WhenStructLayout specifies a Size, a constant is generated:
Address Objects
For each method with signature-based attributes (MemberFunction, StaticAddress, VirtualTable), an Address object is generated in the nested Addresses class:
- Name: Fully qualified identifier for debugging
- Signature: Original pattern with wildcards (
??) - Relative Offsets: Array of offsets for following relative jumps/calls
- Signature Bytes: Pattern converted to
ulong[]for fast comparison - Mask Bytes: Mask indicating which bytes to compare (
0xFFfor known,0x00for wildcards) - Value: Resolved address (initialized to
0, filled by resolver)
Delegate Types
Function pointer delegates are generated forMemberFunction and VirtualFunction methods:
Method Implementations
MemberFunction Implementation
- Lazy initialization of function pointer
- Automatic marshaling of
thispointer for non-static methods - Type-safe parameter passing
VirtualFunction Implementation
- Direct virtual table access
- No delegate caching needed (vtable is already a function pointer)
- Minimal overhead
StaticAddress Implementation
isPointer: true:
Virtual Table Struct
For structs with[VirtualTable] and [VirtualFunction] attributes:
- Explicit layout matching native vtable structure
- Function pointers at correct offsets
- Unmanaged calling convention
Fixed-Size Array Accessors
For fields marked with[FixedSizeArray]:
isString: true):
isBitArray: true):
BitField Properties
For fields with[BitField<T>] attributes:
String Overloads
For methods marked with[GenerateStringOverloads]:
Inheritance Code
For structs with[Inherits<T>], a separate file is generated: {StructName}.Inheritance.InteropGenerator.g.cs
Resolver Initialization
A global resolver initialization file is generated:{InteropNamespace}.Addresses.g.cs
Fixed Array Type Generation
A single file is generated for all fixed array types:{InteropNamespace}.FixedArrays.g.cs
Generator Configuration
Configure the generator via MSBuild properties:InteropGenerator.Runtime.Generated
Performance Considerations
Incremental Generation
The generator is fully incremental:- Only regenerates files when their source structs change
- Inheritance trees are cached and reused
- Minimal impact on build times
Runtime Performance
- Delegate caching: Function pointers cached after first use
- Virtual functions: Direct vtable access, no caching overhead
- Fixed arrays: Zero-cost abstraction over raw memory
- Bitfields: Inline bit manipulation, no allocations
Code Size
- Generated code is minimal and focused
- String overloads use
stackallocfor small strings - No reflection or dynamic code generation at runtime
Diagnostics
The generator includes analyzers that emit warnings/errors for:- Invalid attribute usage
- Missing
partialkeyword - Incorrect method signatures
- Invalid signature patterns
- Mismatched inheritance hierarchies
- Invalid bitfield configurations
See Also
- Interop Attributes - Attribute reference
- Address Resolver - Runtime signature scanning
- Best Practices - Recommended patterns