Skip to content

[ffigen] const globals should be proxied in dart(?) #2816

@jacksonrl

Description

@jacksonrl

example:

// test.h

#define MY_MACRO_CONST 100

int my_global_var;

const int my_const_var;

static int my_static_var = 200;

static const int my_static_const_var = 300;

results in this generated code:

// AUTO GENERATED FILE, DO NOT EDIT.
//
// Generated by `package:ffigen`.
// ignore_for_file: type=lint
import 'dart:ffi' as ffi;

/// Testing ffigen variable behavior
class TestBindings {
  /// Holds the symbol lookup function.
  final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
      _lookup;

  /// The symbols are looked up in [dynamicLibrary].
  TestBindings(ffi.DynamicLibrary dynamicLibrary)
      : _lookup = dynamicLibrary.lookup;

  /// The symbols are looked up with [lookup].
  TestBindings.fromLookup(
      ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
          lookup)
      : _lookup = lookup;

  late final ffi.Pointer<ffi.Int> _my_global_var =
      _lookup<ffi.Int>('my_global_var');

  int get my_global_var => _my_global_var.value;

  set my_global_var(int value) => _my_global_var.value = value;

  late final ffi.Pointer<ffi.Int> _my_const_var =
      _lookup<ffi.Int>('my_const_var');

  int get my_const_var => _my_const_var.value;

  set my_const_var(int value) => _my_const_var.value = value;

  late final ffi.Pointer<ffi.Int> _my_static_var =
      _lookup<ffi.Int>('my_static_var');

  int get my_static_var => _my_static_var.value;

  set my_static_var(int value) => _my_static_var.value = value;

  late final ffi.Pointer<ffi.Int> _my_static_const_var =
      _lookup<ffi.Int>('my_static_const_var');

  int get my_static_const_var => _my_static_const_var.value;

  set my_static_const_var(int value) => _my_static_const_var.value = value;
}

const int MY_MACRO_CONST = 100;

I would expect the static const var to just proxy the value in dart, similar to the #define MY_MACRO_CONST 100. Yet it creates setters for it, which doesn't make sense in this context. I think this PR tried to address that: #828

Additionally, if you try to actually use the static const getter, it doesn't actually work because the compiler throws it away and doesn't exist in the lookup table at runtime.(?) At least that is what appeared to be the case for me when I tried to use it in my project, although I could just be doing something wrong. By opening this issue I'm trying to understand what the expected behavior is as I may be misunderstanding something obvious.

I tried looking for existing discussion but could not find any, I hope this is not a duplicate.

Suggestion: treat const and static const like #define in headers. Or maybe just for primitive types like int, bool and float. Headers in some projects contain static consts that act as enums which is why I need this. Willing to open a PR if this is reasonable.

I guess the difficulty here is evaluating the const? As in what to do here:

static const int A = 1;
static const int B = A + 1;  

Still, I think even just special casing it to work only for literals that don't reference any other variables would be useful. Or maybe there is some way to let the user define their own evaluateConstExpression or similar? I did something like this with the dart analyzer once to convert simple dart objects to js, and that worked for my usecase there.

relevant file: https://github.com/dart-lang/native/blob/main/pkgs/ffigen/lib/src/code_generator/constant.dart

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions