lookupFunction delcaration causing obtuse error.

100 views
Skip to first unread message

Brett Sutton

unread,
Sep 23, 2020, 3:00:48 AM9/23/20
to Dart FFI
I'm trying to create a cross-platform wrapper for a number of posix methods.

I was looking to create a class 'Libc' that load the appropriate shared library based on the platform and then have methods call through the libc class.

So I created the following class:

```dart
import 'dart:ffi' as ffi;
import 'dart:io' show Platform;

class Libc {
static final Libc _self = Libc._internal();

ffi.DynamicLibrary dylib;

factory Libc() => _self;

Libc._internal() {
var path = 'libc.so.6';
if (Platform.isMacOS) path = '/usr/lib/libSystem.dylib';
if (Platform.isWindows) path = r'primitives_library\Debug\primitives.dll';
dylib = ffi.DynamicLibrary.open(path);
}

ffi.Pointer<T> lookup<T extends ffi.NativeType>(String funcname) =>
dylib.lookup(funcname);

F lookupFunction<T extends Function, F extends Function>(String symbolName) =>
dylib.lookupFunction(symbolName);
}
```

The problem is with the lookupFunction. If I have it declared (I don't even need to call it) its throwing the following error:

```
Connecting to VM Service at ws://127.0.0.1:44079/FDwsl6ObgHs=/ws
lib/src/posix_bindings.dart: Warning: Interpreting this as package URI, 'package:posix/src/posix_bindings.dart'.
lib/src/unistd/libc.dart:22:13: Error: Expected type 'NativeFunction<Function>' to be a valid and instantiated subtype of 'NativeType'. - 'NativeFunction' is from 'dart:ffi'. - 'Function' is from 'dart:core'. dylib.lookupFunction(symbolName); ^
```

This is the unit test that I'm calling the library from:

```dart 
import 'dart:ffi' as ffi;

import 'package:ffi/ffi.dart';
import 'package:posix/src/unistd/libc.dart';

/// Holds the Dynamic library.
ffi.DynamicLibrary _dylib;

void main() {
var path = 'libc.so.6';
_dylib = ffi.DynamicLibrary.open(path);
print(Utf8.fromUtf8(strerror(2).cast()));
}

/// Return a string describing the meaning of the `errno' code in ERRNUM.
ffi.Pointer<ffi.Int8> strerror(
int __errnum,
) {
var _strerror =
Libc().dylib.lookupFunction<_c_strerror, _dart_strerror>('strerror');
return _strerror(
__errnum,
);
}

typedef _c_strerror = ffi.Pointer<ffi.Int8> Function(
ffi.Int32 __errnum,
);

typedef _dart_strerror = ffi.Pointer<ffi.Int8> Function(
int __errnum,
);
```

Note that the unit tests does not even use the Libc.lookupFunction.



Daco Harkes

unread,
Sep 23, 2020, 4:11:41 AM9/23/20
to Brett Sutton, Dart FFI
HI Brett,

Unfortunately, you cannot use lookupFunction in a generic way.

The technical reason for this is that in ahead of time compilation (used when making release archives for iOS and Android) we need to know all function signatures used for FFI calls in order to be able to generate the right assembly to handle the difference between the native C ABI and the Dart calling convention. Disallowing generic invocations ensures we see all function signatures during compile time.

We are aware this disallows writing useful wrappers around lookupFunction (also asFunction and fromFunction).

Kind regards,

 •  Daco Harkes
 •  Software Engineer
 •  dacoh...@google.com 


--
You received this message because you are subscribed to the Google Groups "Dart FFI" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dart-ffi+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dart-ffi/773fe352-96da-4259-8902-33040da44926n%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages