dna 0.6.1

  • Readme
  • Changelog
  • Installing
  • 46


Dart Native Access lets you deal with native libraries from Dart with zero lines of C/C++ code. Just pure Dart.

How to ... #

For instance, you want to call getppid function from libc library on Linux.

  • Find method signature in documentation:
pid_t getpid(void);
  • Map parameters types and return type to C data types:
typedef int pid_t;
  • Map C data types to Dart types and DNA type constants. See Type mapping.
  • Define class Libc with annotation @Library:
class Libc {

libc.so.6 is library name.

  • Define method getppid. Annotate parameters with @Param and method with @Method with corresponding type constants:
class Libc {
  int getpid();

In this example method has no parameters.

  • Finish with boilerplate code:
class Libc extends DynamicLibrary<Libc> {
  int getpid();

  • Use it
Libc libc = new Libc();
var processId = libc.getpid();

For full code see Examples.

How to define library #

class Library DynamicLibrary<Library> {

name is the OS specific library name. For instance: libname.so or name.dll or libname.dylib.

Please see documentation for the target OS to know where dynamic linker searches for the library.

FIXME: Symlinks aren't supported

How to define method #

@Method(C_XYZ) T method(
  @Param(C_XYZ) T1 inParam, 
  @Param(C_XYZ, out: true) Ref<T2> outParam);

Annotation @Method is used to define C type of return value. Annotation @Param is used to define C type of paramters. C_XYZ is C type constant. See Type mapping. @Method and @Param are optional. See Default mapping.

How to define structure #

class Struct {
    @Field(C_XYZ) T field;

Annotation @Struct is used to define C struct. Annotation @Field is used to define field of C struct. @Field is required. All fields without @Field annotations are ignored.

Type mapping #

Basic types #


Fixed-width types #


Pointers #

char *StringC_STRINGIn
char *Ref<String>C_STRINGOutString must be initialized and have expected by callee size.
char **List<String>LISTSTRINGIn
{integer type} *List<int>C_{type}In
{integer type} *Ref<List<int>>C_{type}Out
{decimal type} *List<double>C_{type}In
{decimal type} *Ref<List<double>>C_{type}Out
{type} *intC_POINTERInRaw pointer value.
{type} *TypedDataTYPEDDATAIn/OutTypeData must be initialized and have expected by callee size.

Structs #

struct *TC_STRUCTIn/OutT is struct class. See Define structure.

Default mapping #


Out parameters #

If parameter modified by callee it must be marked as @Param(..., out: true)

Dart doesn't support parameters by reference. It's good but it's the cause of one challenge: callee cannot override parameter object. For instance, String parameter cannot be modified inside called method.

Therefore, it's needed to use wrapper object to emulate out parameters: Ref<T>.

FIXME: Describe pointers, in/out parameters, String parameters and TypedData parameters


  • I see Failed assertion: 'libraryPointer != 0

Dynamic linker cannot find the library. Check the library name.

  • I see Failed assertion: 'methodPointer != 0

Dynamic linker cannot find method in the library. Check the method name. Check that library exports the method.

  • My library is cross platform and has different name on each platform.

See example.

@Library('libname.so', 'name.dll')
class Library DynamicLibrary<Library> {

  • My library doesn't export functions or/and uses custom logic to get function pointer

See example.

class Library DynamicLibrary<Library> {
  Library() : super(getMethodPointer);

  static int getMethodPointer(DynamicLibrary that, Invocation invocation) {
    return ... //raw function pointer here

Examples #

Linux #

libc library #

class Libc extends DynamicLibrary<Libc>  {
  int getpid();

  int getuid();
  int getgid();

  int getgroups(int count, @Param(C_INT) Ref<List<int>> groups);
  int rand();
  int rand_r(@Param(C_INT) Ref<List<int>> seedp);
  void srand(@Param(C_UINT) int seed);

void main() {
  var libc = new Libc();

  var processId = libc.getpid();
  print('pid $processId');

  var userId = libc.getuid();
  print('user id ${userId}');

  var groupId = libc.getgid();
  print('group id ${groupId}');

  var n = libc.getgroups(0, new Ref(new List()));
  var groups = new Ref(new List<int>.filled(n, 0));
  libc.getgroups(n, groups);
  print('groups ${groups.value}');

  var rand = libc.rand();
  print('random $rand');

  var seed = new Ref([0xDEADBEE]);
  var srand = libc.rand_r(seed);
  print('random with seed $srand');

Windows #

kenel32 library #

class Kernel32 extends DynamicLibrary<Kernel32> {

  static const int DWORD = C_ULONG;
  static const int HANDLE = C_POINTER;
  static const int HMODULE = HANDLE;  
  static const int PSIZE_T = C_POINTER;
  int GetCurrentProcess();

  int GetProcessId(
    @Param(HANDLE) int process);

  int GetModuleFileNameA(
      @Param(HMODULE) int process,
      @Param(C_STRING) Ref<String> imageFileName,
      @Param(DWORD) int size);

  bool GetProcessWorkingSetSize(
      @Param(HANDLE) int process,
      @Param(PSIZE_T) Ref<List<int>> minimumWorkingSetSize,
      @Param(PSIZE_T) Ref<List<int>> maximumWorkingSetSize);

  int GetLastError();

void main() {
  Kernel32 kernel32 = new Kernel32();
  var process = kernel32.GetCurrentProcess();
  var processId = kernel32.GetProcessId(process);
  print('pid $processId = ${io.pid}');

  var min = new Ref([0]);
  var max = new Ref([0]);
  kernel32.GetProcessWorkingSetSize(process, min, max);
  print('working set min ${min.value} max ${max.value} error ${kernel32.GetLastError()}');

  var name = new Ref<String>(new String.fromCharCodes(new List.filled(64, 0)));
  var length = kernel32.GetModuleFileNameA(0, name, name.value.length);
  print('module name ${name.value.substring(0, length)} error ${kernel32.GetLastError()}');

Please find more examples in examples/.

Requirements #

  • Linux 64-bit
  • Windows 64-bit

To Do #

  • Improve performance
  • A lot of things aren't supported yet
    • Function pointers to Dart methods
    • Custom structure align
    • Unions
    • ...
  • Mac OS support
  • Refactor and clean up code

Changelog #

0.6 #

  • Structure alignment and padding
  • Structure fields by reference
  • Nested structures by value and by reference

0.5 #

  • Refactoring
  • Fixed-length data types support

0.4 #

  • Refactoring
  • Improve performance

0.3 #

  • Nested structure support

0.2 #

  • Structure support

0.1 #

  • Initial version

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:

  dna: ^0.6.1

2. Install it

You can install packages from the command line:

with pub:

$ pub get

Alternatively, your editor might support pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:

import 'package:dna/dna.dart';
Describes how popular the package is relative to other packages. [more]
Code health derived from static analysis. [more]
Reflects how tidy and up-to-date the package is. [more]
Weighted score of the above. [more]
Learn more about scoring.

We analyzed this package on Jan 25, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.0
  • pana: 0.13.4

Health issues and suggestions

Document public APIs. (-0.48 points)

56 out of 57 API elements have no dartdoc comment.Providing good documentation for libraries, classes, functions, and other API elements improves code readability and helps developers find and use your API.

Fix lib/src/coder.dart. (-7.24 points)

Analysis of lib/src/coder.dart reported 15 hints, including:

line 29 col 15: Unnecessary new keyword.

line 55 col 15: Unnecessary new keyword.

line 88 col 22: Unnecessary new keyword.

line 101 col 21: Unnecessary new keyword.

line 112 col 27: Unnecessary new keyword.

Fix lib/src/meta.dart. (-7.24 points)

Analysis of lib/src/meta.dart reported 15 hints, including:

line 36 col 25: Unnecessary new keyword.

line 51 col 21: Unnecessary new keyword.

line 52 col 21: Unnecessary new keyword.

line 72 col 27: Unnecessary new keyword.

line 75 col 23: Unnecessary new keyword.

Fix lib/src/util.dart. (-5.84 points)

Analysis of lib/src/util.dart reported 12 hints, including:

line 29 col 13: Unnecessary new keyword.

line 40 col 13: Unnecessary new keyword.

line 59 col 13: Unnecessary new keyword.

line 72 col 13: Unnecessary new keyword.

line 82 col 14: Unnecessary new keyword.

Fix additional 12 files with analysis or formatting issues. (-1 points)

Additional issues in the following files:

  • lib/src/dynamic_library.dart (1 hint)
  • lib/src/util_reflection.dart (1 hint)
  • lib/dna.dart (Run dartfmt to format lib/dna.dart.)
  • lib/src/log.dart (Run dartfmt to format lib/src/log.dart.)
  • lib/src/model/argument.dart (Run dartfmt to format lib/src/model/argument.dart.)
  • lib/src/model/field.dart (Run dartfmt to format lib/src/model/field.dart.)
  • lib/src/model/library_meta.dart (Run dartfmt to format lib/src/model/library_meta.dart.)
  • lib/src/model/param.dart (Run dartfmt to format lib/src/model/param.dart.)
  • lib/src/model/param_meta.dart (Run dartfmt to format lib/src/model/param_meta.dart.)
  • lib/src/sizes.dart (Run dartfmt to format lib/src/sizes.dart.)
  • lib/src/types.dart (Run dartfmt to format lib/src/types.dart.)
  • lib/src/util_c.dart (Run dartfmt to format lib/src/util_c.dart.)

Maintenance suggestions

Package is getting outdated. (-43.84 points)

The package was last published 75 weeks ago.

Maintain an example.

None of the files in the package's example/ directory matches known example patterns.

Common filename patterns include main.dart, example.dart, and dna.dart. Packages with multiple examples should provide example/README.md.

For more information see the pub package layout conventions.


Package Constraint Resolved Available
Direct dependencies
Dart SDK >=1.0.0 <3.0.0
Dev dependencies
test 1.3.0