# When to Use the `gdsync` Attribute in gdext-nim for Godot Method Registration

> Discover when to use the gdsync attribute in gdext-nim for Godot. Register Nim methods for seamless GDScript, C#, and editor integration. Unlock powerful cross-language communication.

- Repository: [godot-nim 4+/gdext-nim](https://github.com/godot-nim/gdext-nim)
- Tags: api-reference
- Published: 2026-03-02

---

**The `{.gdsync.}` pragma macro registers Nim procedures, methods, classes, and signals with the Godot engine, making them callable from GDScript, C#, and the editor.**

The `gdsync` attribute serves as the primary bridge between Nim and Godot in the **godot-nim/gdext-nim** extension. When applied to method definitions, this pragma instructs the code generator to create the necessary binding code that exposes your Nim code to Godot's scripting API and reflection system.

## What the `gdsync` Attribute Does

`{.gdsync.}` is a compile-time macro that processes annotated definitions and generates registration code for the Godot engine. According to the source code in `src/gdext/bridge.nim` (lines 21‑28), the pragma supports classes, procedures, methods, signals, and virtual functions.

### Class Registration

When applied to type definitions, `{.gdsync.}` registers the Nim type as a full Godot class. This allows instantiation from GDScript and visibility within the Godot editor's inspector. The macro description in `bridge.nim` handles the base registration that makes your custom types appear as native Godot classes.

### Method and Virtual Method Binding

For procedures and methods, the attribute triggers two distinct code paths depending on the method type. The `sync_methodDef` macro in `src/gdext/private/userclass/procs.nim` (lines 97‑124) processes ordinary methods, while `sync_virtualDef` in `src/gdext/private/userclass/virtuals.nim` (lines 62‑71) handles virtual method overrides. These macros generate the boilerplate that translates between Godot's calling conventions and Nim's execution context.

### Signal Registration

When combined with the `{.signal.}` pragma, `{.gdsync.}` registers a function as a Godot signal. As documented in `src/gdext/bridge.nim` (lines 39‑44), signal procedures must return the `Error` type. The attribute ensures the signal appears in Godot's signal connection dialog and can be emitted to other scripts.

## When to Use `gdsync` on Method Definitions

Apply the `gdsync` attribute whenever the method must appear in Godot's reflection system. Omit it for purely internal Nim code.

- **Public API methods** – Add `{.gdsync.}` to gameplay logic, utility functions, or any procedure that GDScript or C# scripts need to invoke. This makes the method part of the Godot class interface.

- **Virtual method overrides** – Use `{.gdsync.}` when overriding Godot-provided virtuals like `_process`, `_physics_process`, or custom virtuals defined in base classes. The attribute registers the override so the engine can call it at the appropriate time via the `sync_virtualDef` implementation.

- **Signal emitters** – Apply both `{.gdsync.}` and `{.signal.}` to procedures that return `Error` and need to be connectable from other scripts.

- **RPC-enabled methods** – Combine `{.gdsync.}` with `{.rpc.}` for networked functions. This allows remote invocation while maintaining registration as a normal method.

- **Internal helpers** – **Do not** add `{.gdsync.}` to private utility functions, forward declarations, or implementation details. The macro emits warnings when applied to internal methods and ignores them, as the engine never needs visibility into these procedures.

## Practical Code Examples

### Exporting a Public Method

This example from `src/gdext/wizard/subcommands/extension/template/src/classes/gdmyclass.nim` (lines 12‑14) shows a basic exported method:

```nim
type MyClass* {.gdsync.} = ptr object of Node

proc hello(self: MyClass; name: String): String {.gdsync.} =
  ## This method can be called from GDScript:

  ##   var result = my_class.hello("world")

  "Hello, " & name

```

### Overriding Virtual Methods

Virtual methods require `{.gdsync.}` so Godot can dispatch engine callbacks to your Nim implementation. From `testproject/runtime/nim/src/classes/gdvirtualnode01.nim` (line 7):

```nim
type VirtualNode01* {.gdsync.} = ptr object of Node

method _process(self: VirtualNode01; delta: float) {.gdsync.} =
  ## Runs every physics frame in Godot.

  self.rotate_y(delta)

```

### Defining Signals

Signals must return `Error` and use both `gdsync` and `signal` pragmas. From `gdmyclass.nim` (lines 22‑23):

```nim
proc mySignal(self: MyClass): Error {.gdsync, signal.} =
  ## Emitted when something important happens.

  ok

```

### RPC-Enabled Methods

Combine `gdsync` with `rpc` to expose networked functions. From `testproject/runtime/nim/src/classes/gdfunctiontester.nim` (line 60):

```nim
proc syncValue(self: MyClass; v: int) {.gdsync, rpc(callLocal = true).} =
  ## Called remotely, but also registered as a normal method.

  self.set_value(v)

```

### Internal Helper Methods

Keep internal utilities free of the pragma to avoid unnecessary registration overhead:

```nim
proc helper(self: MyClass; x: int): int =
  ## Private helper; not exposed to Godot.

  x * 2

```

## How `gdsync` Works Under the Hood

The implementation relies on compile-time macro expansion defined across several core files. In `src/gdext/private/userclass/procs.nim`, the `sync_methodDef` macro (lines 97‑124) generates the binding code that wraps Nim procedures for Godot's method system. For virtual methods, `src/gdext/private/userclass/virtuals.nim` contains `sync_virtualDef` (lines 62‑71), which creates the virtual table entries Godot uses to dispatch calls to `_process`, `_ready`, and other lifecycle methods.

The central definition in `src/gdext/bridge.nim` coordinates these behaviors, accepting modifier pragmas like `{.base.}`, `{.singleton.}`, `{.tool.}`, and `{.icon.}` alongside `{.gdsync.}` to fine-tune registration parameters.

## Summary

- **`{.gdsync.}`** registers Nim definitions with Godot's engine, making them visible to GDScript and the editor.
- **Apply it** to public API methods, virtual overrides, signals, and RPC functions that need engine visibility.
- **Omit it** for private helpers and internal implementation details to avoid compiler warnings and unnecessary binding generation.
- The pragma triggers `sync_methodDef` for regular procedures and `sync_virtualDef` for virtual method overrides during compilation.
- Combine with `{.signal.}`, `{.rpc.}`, or other modifiers to extend functionality while maintaining Godot interoperability.

## Frequently Asked Questions

### What happens if I forget to add `gdsync` to a public method?

The method compiles as normal Nim code but remains invisible to Godot. GDScript cannot call it, it won't appear in the editor's autocomplete, and the engine's reflection system won't recognize it as part of your class interface. You must add `{.gdsync.}` to generate the necessary binding code in `sync_methodDef`.

### Can I combine `gdsync` with other pragmas?

Yes. The `bridge.nim` implementation supports combining `{.gdsync.}` with modifiers like `{.signal.}`, `{.rpc.}`, `{.tool.}`, `{.singleton.}`, and `{.icon.}`. These combinations fine-tune how the item appears and behaves within the Godot editor and runtime.

### Does `gdsync` affect performance?

The pragma itself adds minimal runtime overhead since it operates at compile time to generate binding code. However, methods registered with `{.gdsync.}` participate in Godot's virtual dispatch system, which involves slight indirection compared to direct Nim procedure calls. For hot paths, keep critical internal logic in `{.gdsync.}`-free helper functions.

### How do I expose virtual methods like `_process` or `_ready`?

Define them as Nim methods with `{.gdsync.}` and the appropriate signature. The `sync_virtualDef` macro in `virtuals.nim` registers these with Godot's virtual table, allowing the engine to call your implementation during the scene tree update cycles. Without the pragma, Godot cannot find your override and will use the base class implementation instead.