Skip to content

Raw Pointer Interop

Andrew Lind edited this page Jul 2, 2026 · 1 revision

Binding to hand-written C that traffics in raw pointers — a native struct with a T* member, a fixed C array T[N], or an opaque void* payload — needs the hxcpp pointer interop family. Hatchet lowers those types to native C++ pointers and recognises the cpp.Pointer .raw idioms hxcpp uses to produce them, so the same Haxe source that satisfies hxcpp transpiles to the equivalent C++98.

Pointer interop types

Haxe C++98 Notes
cpp.Pointer<T> T* The general hxcpp pointer wrapper
cpp.RawPointer<T> T* A bare native pointer
cpp.Star<T> T* Synonym for a native pointer
cpp.ConstStar<T> const T* A pointer to const
cpp.Void void So cpp.RawPointer<cpp.Void> / cpp.Star<cpp.Void> give void*

They resolve at every use site — field, parameter, local, return — and index as C pointers (p[i]), so a Haxe binding to a native struct member transpiles faithfully:

@:native("ns::Vertex") typedef Vertex = {
  var position:Vec3;
  @:optional var weights:cpp.RawPointer<cpp.Float32>;   // -> float* weights;
}

Dynamic / Any are the opaque void*

In an emitted position, Dynamic and Any erase to void* — an opaque pointer that carries anything (Any is abstract Any(Dynamic), so both are Dynamic-backed at runtime). Dynamic also keeps its @:overload-marker role. This is the faithful way to accept and store an untyped payload:

public function new(engine:Engine, type:EffectType, ?data:Dynamic) {
  this.data = cpp.Pointer.fromStar(data).raw;   // this.data is a void* field
}

{} as a void* type is deprecated. With Dynamic (opaque value) and cpp.RawPointer<cpp.Void> (opaque pointer) as the faithful spellings, the empty structure {} used as a void* type now emits a deprecation warning (it still lowers to void* so existing sources keep working — the void* lowering will be removed in a future release).

.raw pointer intrinsics

The cpp.Pointer accessors written to satisfy hxcpp are recognised and lowered:

  • cpp.Pointer.fromStar(x).raw — view x as a raw pointer: emits x when it is already a pointer, else takes its address &(x). The developer's intent to treat x as a void* / T*.
  • cpp.Pointer.ofArray(a).raw — a pointer to the first element, &(a)[0].

See Interop via @proxy for binding native classes, Metadata for extern and @:native, and Types & Nullability for the scalar interop types (cpp.Float32, cpp.UInt8, cpp.ConstCharStar, …).

Clone this wiki locally