> For the complete documentation index, see [llms.txt](https://docs.hex-rays.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hex-rays.com/developer/cpp-sdk/how-tos/cpp-sdk-porting-guide-ida-94.md).

# Porting Guide from IDA 9.x to 9.4

## Introduction

This Porting Guide covers the new address-based (`ea_t`) and copy-based APIs introduced in IDA 9.4 across the C++ SDK, and shows how to migrate from the older pointer-based equivalents (`segment_t*`, `func_t*`, and similar).

{% hint style="info" %}
The legacy APIs are **deprecated but not yet removed**. Existing plugins and scripts continue to compile and run without changes in IDA 9.4.
{% endhint %}

Migrating now ensures your code stays compatible when these APIs are eventually removed.

## Segment API (segment.hpp, segregs.hpp)

The new API replaces `segment_t*` pointer-based functions with `ea_t`-based (address-based) functions and `segment_info_t` copy-based access. This avoids pointer lifetime issues: the new functions use a segment's `start_ea` as a stable handle instead of a raw pointer that can be invalidated.

### New types

| Type              | Description                                                                                                                                                      |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `segment_info_t`  | Copy-based segment descriptor (replaces `segment_t*`). Use `get_segment_info()` to fill it, modify via setters, then call `set_segment_info()` to apply changes. |
| `lock_segment_ea` | RAII helper to lock a segment by address (replaces `lock_segment`).                                                                                              |

### Segment lookup and iteration

| Deprecated (pointer-based) | New (ea-based)                                                  |
| -------------------------- | --------------------------------------------------------------- |
| `getseg(ea)`               | `get_segment_info(&si, ea)`                                     |
| `getnseg(n)`               | `get_segment_ea_by_num(n)` or `get_segment_info_by_num(&si, n)` |
| `get_first_seg()`          | `get_first_segment_ea()`                                        |
| `get_last_seg()`           | `get_last_segment_ea()`                                         |
| `get_next_seg(ea)`         | `get_next_segment_ea(ea)`                                       |
| `get_prev_seg(ea)`         | `get_prev_segment_ea(ea)`                                       |
| `get_segm_by_name(name)`   | `get_segment_ea_by_name(name)`                                  |
| `get_segm_by_sel(sel)`     | `get_segment_ea_by_sel(sel)`                                    |

### Segment enumeration by selector

| Deprecated (pointer-based)                        | New (ea-based)                                      |
| ------------------------------------------------- | --------------------------------------------------- |
| `enumerate_segments_with_selector(sel, func, ud)` | `enumerate_segments_with_selector_ea(sel, visitor)` |

The new function takes a `std::function` visitor (`segment_selector_visitor_t`) that receives each matching segment's `start_ea` instead of a `segment_t*` + `void *ud` callback pair. The visitor returns `BADADDR` to continue and any other value to stop the enumeration (that value is returned to the caller). Because the visitor is a closure, the separate `ud` user-data pointer is no longer needed.

Before (deprecated):

```cpp
static ea_t idaapi visit(segment_t *s, void *ud)
{
  msg("segment at %a\n", s->start_ea);
  return BADADDR;  // keep going
}
enumerate_segments_with_selector(sel, visit, nullptr);
```

After (new API):

```cpp
enumerate_segments_with_selector_ea(sel,
    [](ea_t seg_start_ea) -> ea_t
    {
      msg("segment at %a\n", seg_start_ea);
      return BADADDR;  // keep going
    });
```

### Segment creation

| Deprecated (pointer-based)                     | New (segment\_info\_t-based)             |
| ---------------------------------------------- | ---------------------------------------- |
| `add_segm_ex(segment_t*, name, sclass, flags)` | `add_segment_ex(segment_info_t*, flags)` |

### Segment names

| Deprecated (pointer-based)       | New (ea-based)                           |
| -------------------------------- | ---------------------------------------- |
| `get_segm_name(&buf, s, flags)`  | `get_segment_name(&buf, ea, flags)`      |
| `get_visible_segm_name(&buf, s)` | `get_segment_name(&buf, ea, GN_VISIBLE)` |
| `set_segm_name(s, name, flags)`  | `set_segment_name(ea, name, flags)`      |

### Segment class and type

| Deprecated (pointer-based)         | New (ea-based)                         |
| ---------------------------------- | -------------------------------------- |
| `get_segm_class(&buf, s)`          | `get_segment_class(&buf, ea)`          |
| `set_segm_class(s, sclass, flags)` | `set_segment_class(ea, sclass, flags)` |

### Segment comments

| Deprecated (pointer-based)             | New (ea-based)                                |
| -------------------------------------- | --------------------------------------------- |
| `get_segment_cmt(&buf, s, repeatable)` | `get_segment_cmt_by_ea(&buf, ea, repeatable)` |
| `set_segment_cmt(s, cmt, repeatable)`  | `set_segment_cmt_by_ea(ea, cmt, repeatable)`  |

### Segment addressing and base

| Deprecated (pointer-based)        | New (ea-based)                        |
| --------------------------------- | ------------------------------------- |
| `get_segm_para(s)`                | `get_segment_para(ea)`                |
| `get_segm_base(s)`                | `get_segment_base(ea)`                |
| `set_segm_base(s, newbase)`       | `set_segment_base_ea(ea, newbase)`    |
| `set_segm_addressing(s, bitness)` | `set_segment_addressing(ea, bitness)` |

### Segment movement and status

| Deprecated (pointer-based)              | New (ea-based)                                 |
| --------------------------------------- | ---------------------------------------------- |
| `move_segm(s, to, flags)`               | `move_segment(ea, to, flags)`                  |
| `change_segment_status(s, is_deb_segm)` | `change_segment_status_by_ea(ea, is_deb_segm)` |

### Segment visibility

| Deprecated (pointer-based)     | New (ea-based)                     |
| ------------------------------ | ---------------------------------- |
| `set_visible_segm(s, visible)` | `set_visible_segment(ea, visible)` |

### Segment locking

| Deprecated (pointer-based)  | New (ea-based)                 |
| --------------------------- | ------------------------------ |
| `lock_segm(segm, lock)`     | `lock_segment_by_ea(ea, lock)` |
| `lock_segment` (RAII class) | `lock_segment_ea` (RAII class) |
| `is_segm_locked(segm)`      | `is_segment_locked(ea)`        |

### Address adjustment

| Deprecated (pointer-based)   | New (ea-based)                   |
| ---------------------------- | -------------------------------- |
| `segm_adjust_diff(s, delta)` | `adjust_segment_diff(ea, delta)` |
| `segm_adjust_ea(s, ea)`      | `adjust_segment_ea(seg_ea, ea)`  |

### Output helpers

| Deprecated (pointer-based)      | New (ea-based)                        |
| ------------------------------- | ------------------------------------- |
| `std_out_segm_footer(ctx, seg)` | `std_out_segment_footer(ctx, seg_ea)` |

### Segment registers (segregs.hpp)

| Deprecated (pointer-based)              | New (ea-based)                                 |
| --------------------------------------- | ---------------------------------------------- |
| `set_default_sreg_value(sg, rg, value)` | `set_default_sreg_value_ea(seg_ea, rg, value)` |

### Migration example

Before (deprecated):

```cpp
segment_t *s = getseg(ea);
if ( s != nullptr )
{
  qstring name;
  get_segm_name(&name, s);
  msg("segment: %s, bitness: %d\n", name.c_str(), s->bitness);
  set_segm_addressing(s, 2);
}
```

After (new API):

```cpp
segment_info_t si;
if ( get_segment_info(&si, ea, GSI_NAME) )
{
  msg("segment: %s, bitness: %d\n", si.get_name(), si.get_bitness());
  set_segment_addressing(ea, 2);
}
```

## Source file API (lines.hpp)

| Deprecated (pointer-based)   | New (safe)                                    | Notes                                                                                                                       |
| ---------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `get_sourcefile(ea, bounds)` | `get_sourcefile_by_ea(&filename, ea, bounds)` | Returns `bool`; copies filename into `qstring*` instead of returning an internal `const char*` pointer with lifetime issues |

## Hidden range API (bytes.hpp)

The new API replaces `hidden_range_t*` pointer-based functions with `ea_t`-based (address-based) functions and `hidden_range_info_t` copy-based access. This avoids pointer lifetime issues: the new functions use a range's `start_ea` as a stable handle instead of a raw pointer that can be invalidated.

### New types

| Type                  | Description                                                                                                                                                                             |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `hidden_range_info_t` | Copy-based hidden range descriptor (replaces `hidden_range_t*`). Use `get_hidden_range_info()` to fill it, modify via setters, then call `update_hidden_range_info()` to apply changes. |

### Lookup and iteration

| Deprecated (pointer-based)  | New (ea-based / copy-based)             |
| --------------------------- | --------------------------------------- |
| `get_hidden_range(ea)`      | `get_hidden_range_info(&hri, ea)`       |
| `getn_hidden_range(n)`      | `get_hidden_range_info_by_num(&hri, n)` |
| `get_first_hidden_range()`  | `get_first_hidden_range_ea()`           |
| `get_last_hidden_range()`   | `get_last_hidden_range_ea()`            |
| `get_next_hidden_range(ea)` | `get_next_hidden_range_ea(ea)`          |
| `get_prev_hidden_range(ea)` | `get_prev_hidden_range_ea(ea)`          |

### Update

| Deprecated (pointer-based)             | New (copy-based)                 |
| -------------------------------------- | -------------------------------- |
| `update_hidden_range(hidden_range_t*)` | `update_hidden_range_info(&hri)` |

### Migration example

Before (deprecated):

```cpp
hidden_range_t *hr = get_hidden_range(ea);
if ( hr != nullptr )
{
  msg("hidden: %s, visible: %d\n", hr->description, hr->visible);
  hr->visible = true;
  update_hidden_range(hr);
}
```

After (new API):

```cpp
hidden_range_info_t hri;
if ( get_hidden_range_info(&hri, ea) )
{
  msg("hidden: %s, visible: %d\n", hri.get_description(), hri.get_visible());
  hri.set_visible(true);
  update_hidden_range_info(&hri);
}
```

## Output context API (ua.hpp)

### outctx\_t virtual methods

| Deprecated (pointer-based)                 | New (ea-based)                        |
| ------------------------------------------ | ------------------------------------- |
| `outctx_t::gen_func_header(func_t*)`       | `outctx_t::gen_function_header(ea_t)` |
| `outctx_t::gen_func_footer(const func_t*)` | `outctx_t::gen_function_footer(ea_t)` |

## Function API (funcs.hpp)

The new API replaces `func_t*` pointer-based functions with `ea_t`-based (address-based) functions and copy-based info types. This avoids pointer lifetime issues: `func_t*` can be invalidated by `del_func()`, `add_func()`, `set_func_start/end()`, undo operations, and recursive IDB event callbacks.

Because `func_t` is a union (entry chunks and tail chunks share the same C++ type but use different fields), the new API provides two distinct copy types: `func_entry_info_t` for function entries and `func_tail_info_t` for tails.

### New types

| Type                         | Description                                                                                                                                                                                                    |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `fchunk_info_t`              | Lightweight chunk descriptor (range + flags) for entry or tail chunks. Base class for `func_entry_info_t` and `func_tail_info_t`. Use `get_fchunk_info()` to fill.                                             |
| `func_entry_info_t`          | Copy-based function entry descriptor (extends `fchunk_info_t`). Use `get_func_entry_info()` to fill, modify via setters, then call `set_func_entry_info()` to apply changes. Controlled by `GFI_*` fill flags. |
| `func_tail_info_t`           | Copy-based function tail descriptor (extends `fchunk_info_t`). Use `get_func_tail_info()` to fill. Exposes owner, flags, referer count. Use `func_parent_iterator_t` for full referer enumeration.             |
| `function_tail_iterator_t`   | ea-based function tail iterator. Replaces `func_tail_iterator_t(pfn, ea)` with `function_tail_iterator_t(func_ea, ea)`.                                                                                        |
| `function_parent_iterator_t` | ea-based function parent iterator. Replaces `func_parent_iterator_t(fnt)` with `function_parent_iterator_t(tail_ea)`.                                                                                          |
| `function_item_iterator_t`   | ea-based function item iterator. Replaces `func_item_iterator_t(pfn, ea)` with `function_item_iterator_t(func_ea, ea)`.                                                                                        |
| `func_chunk_visitor_t`       | `std::function<void(ea_t chunk_start, ea_t chunk_end)>` callback type for `iterate_func_chunks_ea()`.                                                                                                          |
| `lock_func_ea`               | RAII helper to lock a function by address (replaces `lock_func`).                                                                                                                                              |

### Fill flags for get\_func\_entry\_info()

| Flag           | Description                     |
| -------------- | ------------------------------- |
| `GFI_NAME`     | Populate the function name      |
| `GFI_CMT`      | Populate the regular comment    |
| `GFI_CMT_RPT`  | Populate the repeatable comment |
| `GFI_COMMENTS` | `GFI_CMT \| GFI_CMT_RPT`        |
| `GFI_ALL`      | `GFI_NAME \| GFI_COMMENTS`      |

Numeric fields (flags, frsize, frregs, argsize, fpd, color, frame\_id) are always populated. String fields (name, comments) are only populated when the corresponding `GFI_*` flag is passed, to avoid unnecessary work.

### Function lookup and navigation

| Deprecated (pointer-based) | New (ea-based)                                                  |
| -------------------------- | --------------------------------------------------------------- |
| `get_func(ea)`             | `get_func_start(ea)` or `get_func_entry_info(&fi, ea)`          |
| `getn_func(n)`             | `get_func_ea_by_num(n)` or `get_func_entry_info_by_num(&fi, n)` |
| `get_prev_func(ea)`        | `get_prev_func_ea(ea)`                                          |
| `get_next_func(ea)`        | `get_next_func_ea(ea)`                                          |

### Function chunk lookup and navigation

| Deprecated (pointer-based) | New (ea-based)                                                                        |
| -------------------------- | ------------------------------------------------------------------------------------- |
| `get_fchunk(ea)`           | `get_fchunk_start(ea)`, `get_fchunk_info(&fci, ea)`, or `get_func_tail_info(&ti, ea)` |
| `getn_fchunk(n)`           | `get_fchunk_ea_by_num(n)`                                                             |
| `get_prev_fchunk(ea)`      | `get_prev_fchunk_info(&fci, ea)` or `get_prev_fchunk_ea(ea)`                          |
| `get_next_fchunk(ea)`      | `get_next_fchunk_info(&fci, ea)` or `get_next_fchunk_ea(ea)`                          |

### Function creation

| Deprecated (pointer-based)                | New (ea-based)                     |
| ----------------------------------------- | ---------------------------------- |
| `add_func_ex(pfn)` / `add_func(ea1, ea2)` | `add_function_ex(&fi)`             |
| `find_func_bounds(nfn, flags)`            | `find_function_bounds(&fi, flags)` |

### Function properties

| Deprecated (pointer-based)     | New (ea-based)                                                                         |
| ------------------------------ | -------------------------------------------------------------------------------------- |
| `pfn->flags`                   | `get_func_flags(ea)` / `set_func_flags(ea, flags)` / `set_func_flag(ea, flag, on_off)` |
| `is_func_entry(pfn)`           | `is_function_entry(ea)`                                                                |
| `is_func_tail(pfn)`            | `is_function_tail(ea)`                                                                 |
| `pfn->owner` (tail chunk)      | `get_tail_owner(tail_ea)`                                                              |
| `get_func_bitness(pfn)`        | `get_func_bitness_ea(ea)`                                                              |
| `get_func_bits(pfn)`           | `get_func_bitness_ea(ea)`                                                              |
| `get_func_bytes(pfn)`          | `get_func_bitness_ea(ea)`                                                              |
| `calc_func_size(pfn)`          | `calc_func_size_ea(ea)`                                                                |
| `get_func_ranges(ranges, pfn)` | `get_func_ranges_ea(ranges, ea)`                                                       |
| `update_func(pfn)`             | `set_func_entry_info(&fi)`                                                             |

### Function comments

| Deprecated (pointer-based)     | New (ea-based)                   |
| ------------------------------ | -------------------------------- |
| `get_func_cmt(&buf, pfn, rpt)` | `get_func_cmt_ea(&buf, ea, rpt)` |
| `set_func_cmt(pfn, cmt, rpt)`  | `set_func_cmt_ea(ea, cmt, rpt)`  |

### Function visibility

| Deprecated (pointer-based)     | New (ea-based)                                     |
| ------------------------------ | -------------------------------------------------- |
| `is_visible_func(pfn)`         | `(get_func_flags(ea) & FUNC_HIDDEN) == 0`          |
| `is_finally_visible_func(pfn)` | check `SCF_SHHID_FUNC` flag + `get_func_flags(ea)` |
| `set_visible_func(pfn, vis)`   | `set_visible_func_ea(ea, vis)`                     |

### Function chunk manipulation

| Deprecated (pointer-based)            | New (ea-based)                                |
| ------------------------------------- | --------------------------------------------- |
| `get_func_chunknum(pfn, ea)`          | `get_func_chunknum_ea(func_ea, ea)`           |
| `func_contains(pfn, ea)`              | `function_contains(func_ea, ea)`              |
|                                       | `is_same_fchunk(ea1, ea2)`                    |
| `append_func_tail(pfn, ea1, ea2)`     | `append_func_tail_ea(func_ea, ea1, ea2)`      |
| `remove_func_tail(pfn, tail_ea)`      | `remove_func_tail_ea(func_ea, tail_ea)`       |
| `set_tail_owner(fnt, new_owner)`      | `set_tail_owner_ea(tail_ea, new_owner)`       |
| `iterate_func_chunks(pfn, cb, ud)`    | `iterate_func_chunks_ea(func_ea, visitor)`    |
| `calc_thunk_func_target(pfn, fptr)`   | `calc_thunk_function_target(fi, fptr)`        |
| `set_func_name_if_jumpfunc(pfn, old)` | `set_function_name_if_jumpfunc(func_ea, old)` |
| `reanalyze_function(pfn, ea1, ea2)`   | `reanalyze_function_ea(func_ea, ea1, ea2)`    |
| `pfn->tailqty`                        | `get_func_tail_qty(func_ea)`                  |
| `pfn->tailqty` / `pfn->tails[i]`      | `get_func_tails(&out, func_ea)`               |
| `get_prev_func_addr(pfn, ea)`         | `get_prev_function_addr(func_ea, ea)`         |
| `get_next_func_addr(pfn, ea)`         | `get_next_function_addr(func_ea, ea)`         |

### Register arguments

| Deprecated (pointer-based)        | New (ea-based)                             |
| --------------------------------- | ------------------------------------------ |
| `add_regarg(pfn, reg, tif, name)` | `add_func_regarg(func_ea, reg, tif, name)` |

### Function locking

| Deprecated (pointer-based) | New (ea-based)               |
| -------------------------- | ---------------------------- |
| `lock_func_range(pfn, lk)` | `lock_func_range_ea(ea, lk)` |
| `lock_func` (RAII class)   | `lock_func_ea` (RAII class)  |
| `is_func_locked(pfn)`      | `is_func_locked_ea(ea)`      |

### Migration examples

**Simple case — check if address is in a function:**

Before (deprecated):

```cpp
func_t *pfn = get_func(ea);
if ( pfn != nullptr )
{
  qstring name;
  get_func_name(&name, pfn->start_ea);
  msg("func: %s, flags: 0x%x\n", name.c_str(), pfn->flags);
  pfn->flags |= FUNC_NORET;
  update_func(pfn);
}
```

After (new API):

```cpp
ea_t func_ea = get_func_start(ea);
if ( func_ea != BADADDR )
{
  qstring name;
  get_func_name(&name, func_ea);
  msg("func: %s, flags: 0x%x\n", name.c_str(), get_func_flags(func_ea));
  set_func_flag(func_ea, FUNC_NORET);
}
```

**Multi-field access — using func\_entry\_info\_t:**

```cpp
func_entry_info_t fi;
if ( get_func_entry_info(&fi, ea, GFI_NAME) )
{
  msg("func: %s, flags: 0x%x, frsize: %d\n",
      fi.get_name(), fi.get_flags(), fi.get_frsize());
  fi.set_flags(fi.get_flags() | FUNC_NORET);
  set_func_entry_info(&fi);
}
```

**Tail chunk handling:**

Before (deprecated):

```cpp
func_t *fch = get_fchunk(ea);
if ( is_func_tail(fch) )
  pfn = get_func(fch->owner);
```

After (new API):

```cpp
ea_t owner = get_tail_owner(ea);
if ( owner != BADADDR )
  ...  // use owner directly as ea_t
```

**Iterating function chunks:**

Before (deprecated):

```cpp
iterate_func_chunks(pfn,
    [](ea_t ea1, ea_t ea2, void *ud) { msg("%a-%a\n", ea1, ea2); },
    nullptr);
```

After (new API):

```cpp
iterate_func_chunks_ea(func_ea,
    [](ea_t chunk_start, ea_t chunk_end) { msg("%a-%a\n", chunk_start, chunk_end); });
```

## Frame API (frame.hpp)

The new API replaces `func_t*` pointer-based frame functions with `ea_t`-based equivalents. Using `ea_t` (the function's start address) as a stable handle avoids pointer lifetime issues.

### Frame manipulation

| Deprecated (pointer-based)                 | New (ea-based)                                    |
| ------------------------------------------ | ------------------------------------------------- |
| `add_frame(pfn, frsize, frregs, argsize)`  | `add_frame_ea(func_ea, frsize, frregs, argsize)`  |
| `del_frame(pfn)`                           | `del_frame_ea(func_ea)`                           |
| `set_frame_size(pfn, frsize, frregs, arg)` | `set_frame_size_ea(func_ea, frsize, frregs, arg)` |
| `get_frame_size(pfn)`                      | `get_frame_size_ea(func_ea)`                      |
| `get_frame_retsize(pfn)`                   | `get_frame_retsize_ea(func_ea)`                   |
| `get_frame_part(&range, pfn, part)`        | `get_frame_part_ea(&range, func_ea, part)`        |
| `frame_off_args(pfn)`                      | `frame_off_args_ea(func_ea)`                      |
| `frame_off_retaddr(pfn)`                   | `frame_off_retaddr_ea(func_ea)`                   |
| `frame_off_savregs(pfn)`                   | `frame_off_savregs_ea(func_ea)`                   |
| `frame_off_lvars(pfn)`                     | `frame_off_lvars_ea(func_ea)`                     |
| `get_func_frame(&tif, pfn)`                | `get_func_frame_ea(&tif, func_ea)`                |
| `tinfo_t::get_func_frame(pfn)`             | `tinfo_t::get_function_frame(func_ea)`            |
| `soff_to_fpoff(pfn, soff)`                 | `soff_to_fpoff_ea(func_ea, soff)`                 |
| `update_fpd(pfn, fpd)`                     | `update_fpd_ea(func_ea, fpd)`                     |
| `processor_t::is_funcarg_off(pfn, off)`    | `processor_t::is_funcarg_off_ea(func_ea, off)`    |
| `processor_t::lvar_off(pfn, off)`          | `processor_t::lvar_off_ea(func_ea, off)`          |

Note: `get_frame_part_ea()` returns `bool` (false if no function at func\_ea), improving on the old `void` return type that would crash on nullptr.

### Stack variables

| Deprecated (pointer-based)                        | New (ea-based)                                           |
| ------------------------------------------------- | -------------------------------------------------------- |
| `define_stkvar(pfn, name, off, tif, repr)`        | `define_stkvar_ea(func_ea, name, off, tif, repr)`        |
| `add_frame_member(pfn, name, off, tif, repr, fl)` | `add_frame_member_ea(func_ea, name, off, tif, repr, fl)` |
| `set_frame_member_type(pfn, off, tif, repr, fl)`  | `set_frame_member_type_ea(func_ea, off, tif, repr, fl)`  |
| `delete_frame_members(pfn, soff, eoff)`           | `delete_frame_members_ea(func_ea, soff, eoff)`           |
| `build_stkvar_name(&buf, pfn, v)`                 | `build_stkvar_name_ea(&buf, func_ea, v)`                 |
| `calc_stkvar_struc_offset(pfn, insn, n)`          | `calc_stkvar_struc_offset_ea(func_ea, insn, n)`          |
| `calc_frame_offset(pfn, off, insn, op)`           | `calc_frame_offset_ea(func_ea, off, insn, op)`           |
| `delete_wrong_frame_info(pfn, cb)`                | `delete_wrong_frame_info_ea(func_ea, cb)`                |
| `build_stkvar_xrefs(&out, pfn, soff, eoff)`       | `build_stkvar_xrefs_ea(&out, func_ea, soff, eoff)`       |

### Register variables

| Deprecated (pointer-based)                    | New (ea-based)                                          |
| --------------------------------------------- | ------------------------------------------------------- |
| `add_regvar(pfn, ea1, ea2, canon, user, cmt)` | `add_func_regvar(func_ea, ea1, ea2, canon, user, cmt)`  |
| `find_regvar(pfn, ea1, ea2, canon, user)`     | `find_func_regvar(&rv, func_ea, ea1, ea2, canon, user)` |
| `find_regvar(pfn, ea, canon)`                 | `find_func_regvar(&rv, func_ea, ea, canon)`             |
| `has_regvar(pfn, ea)`                         | `has_func_regvar(func_ea, ea)`                          |
| `rename_regvar(pfn, v, user)`                 | `rename_func_regvar(func_ea, index, user)`              |
| `set_regvar_cmt(pfn, v, cmt)`                 | `set_func_regvar_cmt(func_ea, index, cmt)`              |
| `del_regvar(pfn, ea1, ea2, canon)`            | `del_func_regvar(func_ea, ea1, ea2, canon)`             |
| `pfn->regvarqty` / `pfn->regvars[i]`          | `get_func_regvars(&out, func_ea)`                       |
| `pfn->regvars[i]` (by index)                  | `get_func_regvar(&rv, func_ea, index)`                  |
| `pfn->regvars[i].start_ea/end_ea = ...`       | `set_func_regvar_range(func_ea, index, range)`          |

Unlike the deprecated `find_regvar()`, which returned an unsafe `regvar_t*` pointing into kernel data, `find_func_regvar()` returns the **index** of the register variable (or `-1` if not found) and, when `rv` is not `nullptr`, copies the found regvar into `*rv`. `rename_func_regvar()` / `set_func_regvar_cmt()` take that index. To change a regvar's address range, use `set_func_regvar_range()` (the new range must be well-formed and must keep the variables sorted by `start_ea`):

```cpp
regvar_t rv;
ssize_t index = find_func_regvar(&rv, func_ea, ea, ea+1, nullptr, "ebx");
if ( index != -1 )
  set_func_regvar_range(func_ea, index, range_t(rv.start_ea, new_end));
```

### Register arguments

| Deprecated (pointer-based)           | New (ea-based)                      |
| ------------------------------------ | ----------------------------------- |
| `pfn->regargqty`                     | `get_func_regarg_qty(func_ea)`      |
| `pfn->regargs[i]`                    | `get_func_regarg(&out, func_ea, n)` |
| `pfn->regargqty` / `pfn->regargs[i]` | `get_func_regargs(&out, func_ea)`   |

### Tail referers

| Deprecated (pointer-based)         | New (ea-based)                     |
| ---------------------------------- | ---------------------------------- |
| `pfn->refqty`                      | `get_tail_referer_qty(tail_ea)`    |
| `pfn->refqty` / `pfn->referers[i]` | `get_tail_referer(tail_ea, n)`     |
| `pfn->refqty` / `pfn->referers[i]` | `get_tail_referers(&out, tail_ea)` |

### SP change points

| Deprecated (pointer-based)                | New (ea-based)                                     |
| ----------------------------------------- | -------------------------------------------------- |
| `add_auto_stkpnt(pfn, ea, delta)`         | `add_func_auto_stkpnt(func_ea, ea, delta)`         |
| `del_stkpnt(pfn, ea)`                     | `del_func_stkpnt(func_ea, ea)`                     |
| `get_spd(pfn, ea)`                        | `get_func_spd(func_ea, ea)`                        |
| `get_effective_spd(pfn, ea)`              | `get_func_effective_spd(func_ea, ea)`              |
| `get_sp_delta(pfn, ea)`                   | `get_func_sp_delta(func_ea, ea)`                   |
| `set_auto_spd(pfn, ea, new_spd)`          | `set_func_auto_spd(func_ea, ea, new_spd)`          |
| `recalc_spd_for_basic_block(pfn, cur_ea)` | `recalc_func_spd_for_basic_block(func_ea, cur_ea)` |
| `pfn->pntqty`                             | `get_func_stkpnt_qty(func_ea)`                     |
| `pfn->pntqty` / `pfn->points[i]`          | `get_func_stkpnts(&out, func_ea)`                  |

### Local labels

| Deprecated (pointer-based)           | New (ea-based)                    |
| ------------------------------------ | --------------------------------- |
| `pfn->llabelqty`                     | `get_func_llabel_qty(func_ea)`    |
| `pfn->llabelqty` / `pfn->llabels[i]` | `get_func_llabels(&out, func_ea)` |

Note: For SP change point functions, `func_ea` may be `BADADDR` to auto-resolve the function from the instruction address (matching old nullptr behavior).

**NOT deprecated** (already ea-based or no func\_t\*): `add_stkvar`, `set_purged`, `add_user_stkpnt`, `recalc_spd`, `is_special_frame_member`, `is_anonymous_member_name`, `is_dummy_member_name`, `free_regvar`.

### Migration example

Before (deprecated):

```cpp
func_t *pfn = get_func(ea);
if ( pfn != nullptr )
{
  add_frame(pfn, 0x100, 8, 0);
  define_stkvar(pfn, "my_var", -4, tif);
  sval_t spd = get_spd(pfn, insn.ea);
}
```

After (new API):

```cpp
ea_t func_ea = get_func_start(ea);
if ( func_ea != BADADDR )
{
  add_frame_ea(func_ea, 0x100, 8, 0);
  define_stkvar_ea(func_ea, "my_var", -4, tif);
  sval_t spd = get_func_spd(func_ea, insn.ea);
}
```

## Processor events (processor\_t::event\_t)

### Function events

| Deprecated             | New                           | Parameter change                   |
| ---------------------- | ----------------------------- | ---------------------------------- |
| `ev_is_jump_func`      | `ev_is_jump_function`         | `func_t*` -> `func_entry_info_t *` |
| `ev_func_bounds`       | `ev_function_bounds`          | `func_t*` -> `fchunk_info_t *`     |
| `ev_verify_sp`         | `ev_verify_function_sp`       | `func_t*` -> `ea_t func_ea`        |
| `ev_verify_noreturn`   | `ev_verify_function_noreturn` | `func_t*` -> `ea_t func_ea`        |
| `ev_create_func_frame` | `ev_create_function_frame`    | `func_t*` -> `ea_t func_ea`        |
| `ev_get_frame_retsize` | `ev_get_function_retsize`     | `func_t*` -> `ea_t func_ea`        |

The following events replace `asm_t` callback function pointers:

| Deprecated (`asm_t` callback)                | New (event)              | Parameter change            |
| -------------------------------------------- | ------------------------ | --------------------------- |
| `asm_t::out_func_header(outctx_t&, func_t*)` | `ev_out_function_header` | `func_t*` -> `ea_t func_ea` |
| `asm_t::out_func_footer(outctx_t&, func_t*)` | `ev_out_function_footer` | `func_t*` -> `ea_t func_ea` |

Inline wrappers (`processor_t::` static methods):

| Deprecated                               | New                                            |
| ---------------------------------------- | ---------------------------------------------- |
| `is_jump_func(func_t*, ...)`             | `is_jump_function(func_entry_info_t*, ...)`    |
| `func_bounds(int*, func_t*, ea_t)`       | `function_bounds(int*, ea_t func_ea, ea_t)`    |
| `verify_sp(func_t*)`                     | `verify_function_sp(ea_t func_ea)`             |
| `verify_noreturn(func_t*)`               | `verify_function_noreturn(ea_t func_ea)`       |
| `create_func_frame(func_t*)`             | `create_function_frame(ea_t func_ea)`          |
| `get_frame_retsize(int*, const func_t*)` | `get_function_retsize(int*, ea_t func_ea)`     |
| *(asm\_t callback)*                      | `out_function_header(outctx_t&, ea_t func_ea)` |
| *(asm\_t callback)*                      | `out_function_footer(outctx_t&, ea_t func_ea)` |

### Newly added events

| Event                     | Inline wrapper                       |
| ------------------------- | ------------------------------------ |
| `ev_is_outlined_function` | `is_outlined_function(ea_t func_ea)` |

### Segment events

| Deprecated         | New                    | Parameter change                    |
| ------------------ | ---------------------- | ----------------------------------- |
| `ev_out_segstart`  | `ev_out_segment_start` | `segment_t*` -> `ea_t seg_start_ea` |
| `ev_out_segend`    | `ev_out_segment_end`   | `segment_t*` -> `ea_t seg_start_ea` |
| `ev_creating_segm` | `ev_creating_segment`  | `segment_t*` -> `segment_info_t*`   |
| `ev_moving_segm`   | `ev_moving_segment`    | `segment_t*` -> `ea_t seg_start_ea` |

## IDB events (idb\_event::event\_code\_t)

### Segment events

| Deprecated            | New                      | Parameter change                    |
| --------------------- | ------------------------ | ----------------------------------- |
| `segm_added`          | `segment_added`          | `segment_t*` -> `ea_t seg_start_ea` |
| `changing_segm_start` | `changing_segment_start` | `segment_t*` -> `ea_t seg_start_ea` |
| `segm_start_changed`  | `segment_start_changed`  | `segment_t*` -> `ea_t seg_start_ea` |
| `changing_segm_end`   | `changing_segment_end`   | `segment_t*` -> `ea_t seg_start_ea` |
| `segm_end_changed`    | `segment_end_changed`    | `segment_t*` -> `ea_t seg_start_ea` |
| `changing_segm_name`  | `changing_segment_name`  | `segment_t*` -> `ea_t seg_start_ea` |
| `segm_name_changed`   | `segment_name_changed`   | `segment_t*` -> `ea_t seg_start_ea` |
| `changing_segm_class` | `changing_segment_class` | `segment_t*` -> `ea_t seg_start_ea` |
| `segm_class_changed`  | `segment_class_changed`  | `segment_t*` -> `ea_t seg_start_ea` |
| `segm_attrs_updated`  | `segment_attrs_updated`  | `segment_t*` -> `ea_t seg_start_ea` |
| `adding_segm`         | *(dropped)*              | no replacement                      |

### Function events

| Deprecated                                | New                                                          | Parameter change                                              |
| ----------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------- |
| `func_added(func_t*)`                     | `function_added(ea_t)`                                       | `func_t*` -> `ea_t func_ea`                                   |
| `func_updated(func_t*)`                   | `function_updated(ea_t)`                                     | `func_t*` -> `ea_t func_ea`                                   |
| `set_func_start(func_t*, ea_t)`           | `set_function_start(fchunk_info_t*, ea_t)`                   | `func_t*` -> `fchunk_info_t *fchunk`                          |
| `set_func_end(func_t*, ea_t)`             | `set_function_end(fchunk_info_t*, ea_t)`                     | `func_t*` -> `fchunk_info_t *fchunk`                          |
| `deleting_func(func_t*)`                  | `deleting_function(ea_t)`                                    | `func_t*` -> `ea_t func_ea`                                   |
| `func_tail_appended(func_t*, func_t*)`    | `function_tail_appended(ea_t, func_tail_info_t*)`            | `func_t*` -> `ea_t func_ea`, `func_t*` -> `func_tail_info_t*` |
| `deleting_func_tail(func_t*, range_t*)`   | `deleting_function_tail(ea_t, const range_t*)`               | `func_t*` -> `ea_t func_ea`                                   |
| `func_tail_deleted(func_t*, ea_t)`        | `function_tail_deleted(ea_t, ea_t)`                          | `func_t*` -> `ea_t func_ea`                                   |
| `tail_owner_changed(func_t*, ea_t, ea_t)` | `function_tail_owner_changed(func_tail_info_t*, ea_t, ea_t)` | `func_t*` -> `func_tail_info_t*`                              |
| `func_noret_changed(func_t*)`             | `function_noret_changed(ea_t)`                               | `func_t*` -> `ea_t func_ea`                                   |
| `stkpnts_changed(func_t*)`                | `function_stkpnts_changed(ea_t)`                             | `func_t*` -> `ea_t func_ea`                                   |
| `thunk_func_created(func_t*)`             | `thunk_function_created(ea_t)`                               | `func_t*` -> `ea_t func_ea`                                   |
| `frame_deleted(func_t*)`                  | `function_frame_deleted(ea_t)`                               | `func_t*` -> `ea_t func_ea`                                   |

Note: `func_deleted(ea_t)` already uses `ea_t` — no change needed.

## Flow chart API (gdl.hpp)

The new API replaces `qflow_chart_t` (which stores a `func_t*` pointer) with `qflow_chart_ea_t` (which stores an `ea_t` function address). This avoids pointer lifetime issues: the function's `start_ea` is used as a stable handle instead of a raw `func_t*` that can be invalidated.

### New types

| Type               | Description                                                                                                           |
| ------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `qflow_chart_ea_t` | ea-based flow chart (replaces `qflow_chart_t`). Stores `ea_t func_ea` instead of `func_t *pfn`. Same graph interface. |

### Flow chart construction

| Deprecated (pointer-based)                              | New (ea-based)                                                 |
| ------------------------------------------------------- | -------------------------------------------------------------- |
| `qflow_chart_t(title, pfn, ea1, ea2, flags)`            | `qflow_chart_ea_t(title, func_ea, ea1, ea2, flags)`            |
| `qflow_chart_t::create(title, pfn, ea1, ea2, flags)`    | `qflow_chart_ea_t::create(title, func_ea, ea1, ea2, flags)`    |
| `create_qflow_chart(qflow_chart_t&)`                    | `create_func_flow_chart(qflow_chart_ea_t&)`                    |
| `append_to_flowchart(qflow_chart_t&, ea1, ea2)`         | `append_to_func_flow_chart(qflow_chart_ea_t&, ea1, ea2)`       |
| `fc_calc_block_type(qflow_chart_t&, blknum)`            | `fc_calc_func_block_type(qflow_chart_ea_t&, blknum)`           |
| `create_multirange_qflow_chart(qflow_chart_t&, ranges)` | `create_multirange_func_flow_chart(qflow_chart_ea_t&, ranges)` |
| `gen_flow_graph(file, title, pfn, ea1, ea2, flags)`     | `gen_flow_graph_ea(file, title, func_ea, ea1, ea2, flags)`     |

### Migration example

Before (deprecated):

```cpp
func_t *pfn = get_func(ea);
qflow_chart_t fc("", pfn, pfn->start_ea, pfn->end_ea, 0);
for ( int i = 0; i < fc.size(); i++ )
{
  fc_block_type_t bt = fc.calc_block_type(i);
  msg("block %d: %a-%a type=%d\n", i, fc.blocks[i].start_ea, fc.blocks[i].end_ea, bt);
}
```

After (new API):

```cpp
ea_t func_ea = get_func_start(ea);
qflow_chart_ea_t fc("", func_ea, BADADDR, BADADDR, 0);
for ( int i = 0; i < fc.size(); i++ )
{
  fc_block_type_t bt = fc.calc_block_type(i);
  msg("block %d: %a-%a type=%d\n", i, fc.blocks[i].start_ea, fc.blocks[i].end_ea, bt);
}
```

## Cross-reference API (xref.hpp)

| Deprecated (pointer-based)   | New (ea-based)                      |
| ---------------------------- | ----------------------------------- |
| `has_external_refs(pfn, ea)` | `has_external_refs_ea(func_ea, ea)` |

## Name API (name.hpp)

| Deprecated (pointer-based)                             | New (ea-based)                                                |
| ------------------------------------------------------ | ------------------------------------------------------------- |
| `is_name_defined_locally(pfn, name, ignore, ea1, ea2)` | `is_name_defined_locally_ea(func_ea, name, ignore, ea1, ea2)` |

## Lumina API (lumina.hpp)

| Deprecated (pointer-based)                            | New (ea-based)                                               |
| ----------------------------------------------------- | ------------------------------------------------------------ |
| `calc_func_metadata(hash, fi, pfn, append_metadata)`  | `calc_function_metadata(hash, fi, func_ea, append_metadata)` |
| `metadata_appender_t(mcr, pfn)`                       | `metadata_appender_ea_t(mcr, func_ea)`                       |
| `lumina_client_t::push_md(..., metadata_appender_t*)` | `lumina_client_t::push_md(..., metadata_appender_ea_t*)`     |

The old `lumina_client_t::push_md()` virtual method is renamed to `obsolete_push_md()` (preserving its vtable slot). The new `push_md()` virtual method uses `metadata_appender_ea_t*` and is added after `del_history()`.

## Decompiler API (micro.hpp, c.hpp)

| Deprecated (pointer-based)                             | New (ea-based)                                                |
| ------------------------------------------------------ | ------------------------------------------------------------- |
| `mba_t::get_curfunc()`                                 | `mba_t::get_curfunc_ea()`                                     |
| `cfunc_t::get_curfunc()`                               | `cfunc_t::get_curfunc_ea()`                                   |
| `mba_t::inline_func(cdg, blknum, mba_ranges_t &, ...)` | `mba_t::inline_function(cdg, blknum, decomp_ranges_t &, ...)` |
| `decompile(const mba_ranges_t &, ...)`                 | `decompile(const decomp_ranges_t &, ...)`                     |
| `decompile_func(func_t *pfn, ...)`                     | `decompile_function(ea_t func_ea, ...)`                       |
| `gen_microcode(const mba_ranges_t &, ...)`             | `gen_microcode(const decomp_ranges_t &, ...)`                 |
| `create_empty_mba(const mba_ranges_t &, ...)`          | `create_empty_mba(const decomp_ranges_t &, ...)`              |

`inline_func()` is retained as a thin wrapper that converts its `mba_ranges_t` argument into a `decomp_ranges_t` and delegates to `inline_function()`; new code should call `inline_function()` directly.

`decompile(const mba_ranges_t &, ...)` is retained as a thin wrapper that converts via `set_from_mbr()` and forwards to the new `decompile(const decomp_ranges_t &, ...)` overload; new code should call the ea-based overload directly.

`decompile_snippet(const rangevec_t &, ...)` keeps its name and signature but now builds a `decomp_ranges_t` and calls the new `decompile()` overload, so existing callers do not need to change.

`gen_microcode(const mba_ranges_t &, ...)` is retained as a thin wrapper marked `DEPRECATED`; it converts via `set_from_mbr()` and forwards to the new `gen_microcode(const decomp_ranges_t &, ...)` overload. Similarly, `create_empty_mba(const mba_ranges_t &, ...)` is `DEPRECATED`; use the new `create_empty_mba(const decomp_ranges_t &, ...)` overload instead.

### Migration examples

Before (deprecated):

```cpp
// Decompile a function by pointer
func_t *pfn = get_func(ea);
if ( pfn != nullptr )
{
  hexrays_failure_t hf;
  cfuncptr_t func = decompile(pfn, &hf);  // decompile_func() under the hood
  ...
}

// Decompile an explicit range set
mba_ranges_t mbr(ranges);
cfuncptr_t func = decompile(mbr, &hf);
```

After (new API):

```cpp
// Decompile a function by address
cfuncptr_t func = decompile_function(ea, &hf);

// Or via decomp_ranges_t:
decomp_ranges_t dcr(ea);
cfuncptr_t func = decompile(dcr, &hf);

// Decompile an explicit range set — decompile_snippet() still works, and
// new code can also construct decomp_ranges_t explicitly:
decomp_ranges_t dcr(ranges);
cfuncptr_t func = decompile(dcr, &hf);
```

### Flow chart type in decompiler internals

The internal decompiler code (`codegen_t::analyze_prolog`, `mba_t` flow-chart helpers, processor-module codegen overrides) has been switched from the pointer-based `qflow_chart_t` to the ea-based `qflow_chart_ea_t` (see the Flow chart section above). Plugins that override `codegen_t::analyze_prolog` must update their signature.

| Deprecated (pointer-based)                              | New (ea-based)                                             |
| ------------------------------------------------------- | ---------------------------------------------------------- |
| `codegen_t::analyze_prolog(const qflow_chart_t &, ...)` | `codegen_t::analyze_prolog(const qflow_chart_ea_t &, ...)` |

### Decompiler events (hexrays\_event\_t)

Two new events carry a `qflow_chart_ea_t*` instead of the legacy `qflow_chart_t*`. The decompiler fires the deprecated event first, then the new one, so plugins can migrate at their own pace — existing hooks keep working, and new code should subscribe to the `_ea` variant.

| Deprecated          | New                     | Parameter change                        |
| ------------------- | ----------------------- | --------------------------------------- |
| `hxe_flowchart`     | `hxe_flowchart_ea`      | `qflow_chart_t*` -> `qflow_chart_ea_t*` |
| `hxe_prolog`        | `hxe_prolog_ea`         | `qflow_chart_t*` -> `qflow_chart_ea_t*` |
| `hxe_inlining_func` | `hxe_inlining_function` | `mba_ranges_t*` -> `decomp_ranges_t*`   |
| `hxe_inlined_func`  | `hxe_inlined_function`  | `mba_ranges_t*` -> `decomp_ranges_t*`   |

### Migration example (event handler)

Before (deprecated):

```cpp
case hxe_flowchart:
  {
    qflow_chart_t *fc = va_arg(va, qflow_chart_t *);
    mba_t *mba = va_arg(va, mba_t *);
    bitset_t *reachable = va_arg(va, bitset_t *);
    int decomp_flags = va_argi(va, int);
    // use fc->pfn, fc->blocks, etc.
  }
```

After (new API):

```cpp
case hxe_flowchart_ea:
  {
    qflow_chart_ea_t *fc = va_arg(va, qflow_chart_ea_t *);
    mba_t *mba = va_arg(va, mba_t *);
    bitset_t *reachable = va_arg(va, bitset_t *);
    int decomp_flags = va_argi(va, int);
    // use fc->func_ea, fc->blocks, etc.
  }
```

### Decompilation ranges

The new API replaces `mba_ranges_t` (which stores a `func_t*` pointer) with `decomp_ranges_t` (which stores an `ea_t` function address). The associated iterators are also replaced.

#### New types

| Deprecated (pointer-based) | New (ea-based)            | Description                                    |
| -------------------------- | ------------------------- | ---------------------------------------------- |
| `mba_ranges_t`             | `decomp_ranges_t`         | Ranges to decompile (function or snippet mode) |
| `mba_item_iterator_t`      | `decomp_item_iterator_t`  | Item iterator over decompilation ranges        |
| `mba_range_iterator_t`     | `decomp_range_iterator_t` | Chunk iterator over decompilation ranges       |

Key differences in `decomp_ranges_t` vs `mba_ranges_t`:

* `func_t *pfn` → `ea_t func_ea` (BADADDR when not in function mode)
* Uses `function_item_iterator_t` / `function_tail_iterator_t` instead of `func_item_iterator_t` / `func_tail_iterator_t`
* Uses `function_contains()` and `get_func_tail_qty()` instead of `func_contains()` and `pfn->tailqty`

#### Migration example

Before (deprecated):

```cpp
mba_ranges_t mbr(pfn);
mba_item_iterator_t p;
if ( p.set(mbr) )
  do { ea_t ea = p.current(); ... } while ( p.next_code() );

mba_range_iterator_t ri;
if ( ri.set(mbr) )
  do { range_t r = ri.chunk(); ... } while ( ri.next() );
```

After (new API):

```cpp
decomp_ranges_t mbr(func_ea);
decomp_item_iterator_t p;
if ( p.set(mbr) )
  do { ea_t ea = p.current(); ... } while ( p.next_code() );

decomp_range_iterator_t ri;
if ( ri.set(mbr) )
{
  range_t r;
  do { ri.chunk(&r); ... } while ( ri.next() );
}
```

## Chooser API (kernwin.hpp)

The new API adds ea-based chooser types and inline functions that avoid passing `func_t*` pointers through the `callui()` variadic interface.

### New chooser types

| Deprecated           | New                     |
| -------------------- | ----------------------- |
| `chtype_stkvar_xref` | `chtype_stkvar_xref_ea` |
| `chtype_func`        | `chtype_func_ea`        |

### New chooser functions

| Deprecated (pointer-based)            | New (ea-based)                               |
| ------------------------------------- | -------------------------------------------- |
| `choose_stkvar_xref(pfn, stkvar_tid)` | `choose_stkvar_xref_ea(func_ea, stkvar_tid)` |
| `choose_func(title, default_ea)`      | `choose_func_ea(title, default_ea)`          |

Note: `choose_func()` returns `func_t*`, `choose_func_ea()` returns `ea_t`.

### Migration example

Before (deprecated):

```cpp
func_t *pfn = choose_func("Select function", screen_ea);
if ( pfn != nullptr )
  msg("selected: %a\n", pfn->start_ea);
```

After (new API):

```cpp
ea_t func_ea = choose_func_ea("Select function", screen_ea);
if ( func_ea != BADADDR )
  msg("selected: %a\n", func_ea);
```

## Built-in window API (kernwin.hpp)

### Frame window

| Deprecated (pointer-based)       | New (ea-based)                          |
| -------------------------------- | --------------------------------------- |
| `open_frame_window(pfn, offset)` | `open_frame_window_ea(func_ea, offset)` |

The new function uses `ui_open_builtin2` instead of `ui_open_builtin`.

## UI events (kernwin.hpp)

### Function prototype editor

| Deprecated                                                           | New                                                            |
| -------------------------------------------------------------------- | -------------------------------------------------------------- |
| `ui_prompt_function_prototype_ex` / `prompt_function_prototype_ex()` | `ui_prompt_function_prototype` / `prompt_function_prototype()` |

The new event and inline function take `ea_t func_ea` instead of `func_t *pfn`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.hex-rays.com/developer/cpp-sdk/how-tos/cpp-sdk-porting-guide-ida-94.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
