dna 0.5.3 dna: ^0.5.3 copied to clipboard
Dart Native Access lets you deal with native libraries from Dart with zero lines of C/C++ code. Just pure Dart.
DNA #
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
:
@Library('libc.so.6')
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 #
@Library('name')
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.
- Linux - dlopen
- Mac OS - dlopen
- Windows - LoadLibrary
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);
C_XYZ is C type constant. See Type mapping.
How to define structure #
@Struct()
class Struct {
@Field(C_XYZ) T field;
}
Type mapping #
C | Dart | Constant | In/Out | Comments |
---|---|---|---|---|
void | void |
VOID | In | |
char | int |
C_CHAR | In | |
short | int |
C_SHORT | In | |
int | int |
C_INT | In | |
long | int |
C_LONG | In | |
longlong | int |
C_LONGLONG | In | |
bool | bool |
C_BOOL | In | |
float | double |
C_FLOAT | In |
double | double |
C_DOUBLE | In | |
---|---|---|---|---|
{type} * | int |
C_POINTER | In | Raw pointer value. |
{type} * | TypedData |
TYPEDDATA | In\Out | TypeData must be initialized and have expected by callee size. |
---|---|---|---|---|
struct * | T |
C_STRUCT | In | T is struct class. See Define structure. |
struct * | Ref<T> |
C_STRUCT | Out | T is struct class. See Define structure. |
--- | --- | --- | --- | |
char * | String |
C_STRING | In | |
char * | Ref<String> |
C_STRING | Out | |
char ** | List<String> |
LISTSTRING | In | |
{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 |
Out parameters #
Out parameters 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
FAQ #
- 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.
@Library('name.dll')
class Library DynamicLibrary<Library> {
Library() : super(getMethodPointer);
static int getMethodPointer(DynamicLibrary that, Invocation invocation) {
return ... //raw function pointer here
}
}
Examples #
Linux #
libc library
@Library('libc.so.6')
class Libc extends DynamicLibrary<Libc> {
int getpid();
int getuid();
int getgid();
int getgroups(int count, @Param(C_INT, out: true, list: true) Ref<List<int>> groups);
int rand();
int rand_r(@Param(TYPEDDATA) TypedData 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<List<int>>(new List<int>.filled(n, 0));
libc.getgroups(n, groups);
print('groups ${groups.value}');
libc.srand(0xDEADBEEF);
var rand = libc.rand();
print('random $rand');
var seed = new Uint32List.fromList([0xDEADBEEF]);
var srand = libc.rand_r(seed);
print('random with seed $srand');
}
Windows #
kenel32 library
@Library('Kernel32')
class Kernel32 extends DynamicLibrary<Kernel32> {
int GetCurrentProcess();
int GetProcessId(@Param(C_INT) int process);
int GetModuleFileNameA(
@Param(C_INT) int process,
@Param(C_STRING, out: true) Ref<String> imageFileName,
@Param(C_INT) int size);
bool GetProcessWorkingSetSize(
@Param(C_INT) int process,
@Param(TYPEDDATA) TypedData minimumWorkingSetSize,
@Param(TYPEDDATA) TypedData 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 Uint32List(1);
var max = new Uint32List(1);
kernel32.GetProcessWorkingSetSize(process, min, max);
print('working set min ${min} max ${max} error ${kernel32.GetLastError()}');
var name = new Ref(new String.fromCharCodes(new List.filled(64, 0)));
kernel32.GetModuleFileNameA(0, name, name.value.length);
print('module name ${name.value} error ${kernel32.GetLastError()}');
}
Please find more examples in examples/
.
Requirements #
- Linux 64-bit
- Windows 32-bit and 64-bit
To Do #
- Improve performance
- A lot of things aren't supported yet
- Platform independent types: int8, int16, int32, int64 etc.
- Function pointers to Dart methods
- Custom structure align
- Unions
- ...
- Mac OS support
- Refactor and clean up code