Marvin H.
Marvin H.

Reputation: 1279

Is it possible to initialize a library?

I am trying out the new Dart FFI in making wrappers for libsodium. Libsodium needs to be initialized with calling init(). But I don't think the user should be burdened to remember this and I also wouldn't like to check some global state variable.

I know that Go has package init() functions which run when a package gets included. Is there something similar in Dart?

Of course I could just wrap everything up into a class and run init() in the constructor but there isn't much sense in instatiating a class which basically only exposes static methods. Besides, I would like to preserve the procedural style of libsodium.

Upvotes: 5

Views: 974

Answers (2)

jamesdlin
jamesdlin

Reputation: 89946

Of course I could just wrap everything up into a class and run init() in the constructor but there isn't much sense in instatiating a class which basically only exposes static methods. Besides, I would like to preserve the procedural style of libsodium.

You could have a singleton instance and expose library functions as methods on the instance, and you could provide a public getter function that automatically does initialization.

For example, something like:

Libsodium? _instance;
Libsodium get libsodium => _instance ??= Libsodium._();

class Libsodium {
  Libsodium._() {
    // Do initialization.
  }

  void foo() {
    // ...
  }
  
  void bar() {
    // ...
  }
}

or, taking advantage of Dart initializing global and static variables lazily, that can be simplified to:

final Libsodium libsodium = Libsodium._();

class Libsodium {
  ...
}

and then callers would need to use it via:

import 'libsodium.dart';

libsodium.foo();

This would hide the class instantiation and wouldn't look any different to callers than if you were to use only top-level functions with a namespace (import 'libsodium.dart' as libsodium).

Upvotes: 4

lrn
lrn

Reputation: 71623

Dart does not have any way to implicitly run code. No code runs before main, and all code running after main does so because it was invoked directly or indirectly from the main method. So, no.

If you need something initialized, there is a number of options.

  • You can use a lazily initialized static variable:

    var _initialState = _init();
    int doSomething(arguments) {
      _initialState;
      do the something.
    }
    

    The reading of _initialState will ensure that init is invoked the first time it's needed, and not after that. You can even store things in the state for later use.

  • The singleton implementation object suggested by @jamesdlin. It basically does the same thing, then puts the methods on the object instead of being static. Another variant is to do exactly that, but with a private instance, and have the public top-level functions forward to the singleton object. Then you get the procedural API and still ensures that the state object is initialized. (This may be better for testing, allowing you to have multiple state objects alive at the same time).

  • Require people to call init.

Upvotes: 1

Related Questions