mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[vm/ffi] Change asFunction and lookFunction to extension methods
This prevents them from being called dynamically. Moreover, it prevents asFunction from being called on a non-NativeFunction type argument, simplifying the amount of manual checks. Note that this CL had to change the CFE and analzyer, and their tests (including mock_sdk) as well. This can potentially be a breaking change, as the extension methods are only visible when `dart:ffi` is imported, while methods on objects are always visible. Issue: https://github.com/dart-lang/sdk/issues/35903 Change-Id: I1e291f154228d5d9a34b21a022088bf493f6557d Cq-Include-Trybots: luci.dart.try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-dartkb-linux-release-x64-abi-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try,analyzer-nnbd-linux-release-try,dart2js-nnbd-linux-x64-chrome-try,ddc-nnbd-linux-release-chrome-try,front-end-nnbd-linux-release-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-nnbd-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135463 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
parent
eceb249f88
commit
c1467ab5d3
|
@ -126,12 +126,17 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
|
||||||
Element enclosingElement = element.enclosingElement;
|
Element enclosingElement = element.enclosingElement;
|
||||||
if (enclosingElement is ClassElement) {
|
if (enclosingElement is ClassElement) {
|
||||||
if (_isPointer(enclosingElement)) {
|
if (_isPointer(enclosingElement)) {
|
||||||
if (element.name == 'asFunction') {
|
if (element.name == 'fromFunction') {
|
||||||
_validateAsFunction(node, element);
|
|
||||||
} else if (element.name == 'fromFunction') {
|
|
||||||
_validateFromFunction(node, element);
|
_validateFromFunction(node, element);
|
||||||
}
|
}
|
||||||
} else if (_isDynamicLibrary(enclosingElement) &&
|
}
|
||||||
|
}
|
||||||
|
if (enclosingElement is ExtensionElement) {
|
||||||
|
if (_isNativeFunctionPointerExtension(enclosingElement)) {
|
||||||
|
if (element.name == 'asFunction') {
|
||||||
|
_validateAsFunction(node, element);
|
||||||
|
}
|
||||||
|
} else if (_isDynamicLibraryExtension(enclosingElement) &&
|
||||||
element.name == 'lookupFunction') {
|
element.name == 'lookupFunction') {
|
||||||
_validateLookupFunction(node);
|
_validateLookupFunction(node);
|
||||||
}
|
}
|
||||||
|
@ -152,10 +157,10 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
|
||||||
return element is ClassElement && element.library.name == 'dart.ffi';
|
return element is ClassElement && element.library.name == 'dart.ffi';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` if the given [element] represents the class
|
/// Return `true` if the given [element] represents the extension
|
||||||
/// `DynamicLibrary`.
|
/// `LibraryExtension`.
|
||||||
bool _isDynamicLibrary(ClassElement element) =>
|
bool _isDynamicLibraryExtension(Element element) =>
|
||||||
element.name == 'DynamicLibrary' && element.library.name == 'dart.ffi';
|
element.name == 'LibraryExtension' && element.library.name == 'dart.ffi';
|
||||||
|
|
||||||
/// Returns `true` iff [nativeType] is a `ffi.NativeFunction<???>` type.
|
/// Returns `true` iff [nativeType] is a `ffi.NativeFunction<???>` type.
|
||||||
bool _isNativeFunctionInterfaceType(DartType nativeType) {
|
bool _isNativeFunctionInterfaceType(DartType nativeType) {
|
||||||
|
@ -184,6 +189,10 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
|
||||||
bool _isPointer(Element element) =>
|
bool _isPointer(Element element) =>
|
||||||
element.name == 'Pointer' && element.library.name == 'dart.ffi';
|
element.name == 'Pointer' && element.library.name == 'dart.ffi';
|
||||||
|
|
||||||
|
bool _isNativeFunctionPointerExtension(Element element) =>
|
||||||
|
element.name == 'NativeFunctionPointer' &&
|
||||||
|
element.library.name == 'dart.ffi';
|
||||||
|
|
||||||
/// Returns `true` iff [nativeType] is a `ffi.Pointer<???>` type.
|
/// Returns `true` iff [nativeType] is a `ffi.Pointer<???>` type.
|
||||||
bool _isPointerInterfaceType(DartType nativeType) {
|
bool _isPointerInterfaceType(DartType nativeType) {
|
||||||
if (nativeType is InterfaceType) {
|
if (nativeType is InterfaceType) {
|
||||||
|
|
|
@ -532,13 +532,19 @@ class Pointer<T extends NativeType> extends NativeType {
|
||||||
static Pointer<NativeFunction<T>> fromFunction<T extends Function>(
|
static Pointer<NativeFunction<T>> fromFunction<T extends Function>(
|
||||||
@DartRepresentationOf("T") Function f,
|
@DartRepresentationOf("T") Function f,
|
||||||
[Object exceptionalReturn]);
|
[Object exceptionalReturn]);
|
||||||
R asFunction<@DartRepresentationOf("T") R extends Function>();
|
}
|
||||||
|
extension NativeFunctionPointer<NF extends Function>
|
||||||
|
on Pointer<NativeFunction<NF>> {
|
||||||
|
external DF asFunction<DF extends Function>();
|
||||||
}
|
}
|
||||||
class Struct extends NativeType {}
|
class Struct extends NativeType {}
|
||||||
|
|
||||||
abstract class DynamicLibrary {
|
abstract class DynamicLibrary {}
|
||||||
F lookupFunction<T extends Function, F extends Function>(String symbolName);
|
extension LibraryExtension on DynamicLibrary {
|
||||||
|
external F lookupFunction<T extends Function, F extends Function>(
|
||||||
|
String symbolName);
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class NativeFunction<T extends Function> extends NativeType {}
|
abstract class NativeFunction<T extends Function> extends NativeType {}
|
||||||
|
|
||||||
class DartRepresentationOf {
|
class DartRepresentationOf {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
import 'package:analyzer/src/dart/error/ffi_code.dart';
|
import 'package:analyzer/src/dart/error/ffi_code.dart';
|
||||||
|
import 'package:analyzer/src/error/codes.dart';
|
||||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||||
|
|
||||||
import '../dart/resolution/driver_resolution.dart';
|
import '../dart/resolution/driver_resolution.dart';
|
||||||
|
@ -25,7 +26,9 @@ class C {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
''', [
|
''', [
|
||||||
error(FfiCode.NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER, 109, 1),
|
// This changed from a method to a extension method, uses Dart semantics
|
||||||
|
// instead of manual check now.
|
||||||
|
error(StaticTypeWarningCode.UNDEFINED_METHOD, 98, 10),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,9 +77,6 @@ class C extends Int8 {}
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
class C extends Pointer {}
|
class C extends Pointer {}
|
||||||
''', [
|
''', [
|
||||||
// TODO(brianwilkerson) The following diagnostic should not be generated.
|
|
||||||
error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
|
|
||||||
25, 1),
|
|
||||||
error(FfiCode.SUBTYPE_OF_FFI_CLASS_IN_EXTENDS, 35, 7),
|
error(FfiCode.SUBTYPE_OF_FFI_CLASS_IN_EXTENDS, 35, 7),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -198,9 +195,6 @@ class C implements Int8 {}
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
class C implements Pointer {}
|
class C implements Pointer {}
|
||||||
''', [
|
''', [
|
||||||
// TODO(brianwilkerson) The following diagnostic should not be generated.
|
|
||||||
error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
|
|
||||||
25, 1),
|
|
||||||
error(FfiCode.SUBTYPE_OF_FFI_CLASS_IN_IMPLEMENTS, 38, 7),
|
error(FfiCode.SUBTYPE_OF_FFI_CLASS_IN_IMPLEMENTS, 38, 7),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -333,9 +327,6 @@ class C with Int8 {}
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
class C with Pointer {}
|
class C with Pointer {}
|
||||||
''', [
|
''', [
|
||||||
// TODO(brianwilkerson) The following diagnostic should not be generated.
|
|
||||||
error(StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
|
|
||||||
25, 1),
|
|
||||||
error(CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT, 32, 7),
|
error(CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT, 32, 7),
|
||||||
error(FfiCode.SUBTYPE_OF_FFI_CLASS_IN_WITH, 32, 7),
|
error(FfiCode.SUBTYPE_OF_FFI_CLASS_IN_WITH, 32, 7),
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -234,11 +234,12 @@ class FfiTransformer extends Transformer {
|
||||||
addressOfField = index.getMember('dart:ffi', 'Struct', '_addressOf'),
|
addressOfField = index.getMember('dart:ffi', 'Struct', '_addressOf'),
|
||||||
structFromPointer =
|
structFromPointer =
|
||||||
index.getMember('dart:ffi', 'Struct', '_fromPointer'),
|
index.getMember('dart:ffi', 'Struct', '_fromPointer'),
|
||||||
asFunctionMethod = index.getMember('dart:ffi', 'Pointer', 'asFunction'),
|
asFunctionMethod =
|
||||||
|
index.getMember('dart:ffi', 'NativeFunctionPointer', 'asFunction'),
|
||||||
asFunctionInternal =
|
asFunctionInternal =
|
||||||
index.getTopLevelMember('dart:ffi', '_asFunctionInternal'),
|
index.getTopLevelMember('dart:ffi', '_asFunctionInternal'),
|
||||||
lookupFunctionMethod =
|
lookupFunctionMethod =
|
||||||
index.getMember('dart:ffi', 'DynamicLibrary', 'lookupFunction'),
|
index.getMember('dart:ffi', 'LibraryExtension', 'lookupFunction'),
|
||||||
fromFunctionMethod =
|
fromFunctionMethod =
|
||||||
index.getMember('dart:ffi', 'Pointer', 'fromFunction'),
|
index.getMember('dart:ffi', 'Pointer', 'fromFunction'),
|
||||||
libraryLookupMethod =
|
libraryLookupMethod =
|
||||||
|
|
|
@ -153,7 +153,30 @@ class _FfiUseSiteTransformer extends FfiTransformer {
|
||||||
|
|
||||||
final Member target = node.target;
|
final Member target = node.target;
|
||||||
try {
|
try {
|
||||||
if (target == fromFunctionMethod) {
|
if (target == lookupFunctionMethod && !isFfiLibrary) {
|
||||||
|
final DartType nativeType = InterfaceType(
|
||||||
|
nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
|
||||||
|
final DartType dartType = node.arguments.types[1];
|
||||||
|
|
||||||
|
_ensureNativeTypeValid(nativeType, node);
|
||||||
|
_ensureNativeTypeToDartType(nativeType, dartType, node);
|
||||||
|
return _replaceLookupFunction(node);
|
||||||
|
} else if (target == asFunctionMethod && !isFfiLibrary) {
|
||||||
|
final DartType dartType = node.arguments.types[1];
|
||||||
|
final DartType nativeType = InterfaceType(
|
||||||
|
nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
|
||||||
|
|
||||||
|
_ensureNativeTypeValid(nativeType, node);
|
||||||
|
_ensureNativeTypeToDartType(nativeType, dartType, node);
|
||||||
|
|
||||||
|
final DartType nativeSignature =
|
||||||
|
(nativeType as InterfaceType).typeArguments[0];
|
||||||
|
// Inline function body to make all type arguments instatiated.
|
||||||
|
return StaticInvocation(
|
||||||
|
asFunctionInternal,
|
||||||
|
Arguments([node.arguments.positional[0]],
|
||||||
|
types: [dartType, nativeSignature]));
|
||||||
|
} else if (target == fromFunctionMethod) {
|
||||||
final DartType nativeType = InterfaceType(
|
final DartType nativeType = InterfaceType(
|
||||||
nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
|
nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
|
||||||
final Expression func = node.arguments.positional[0];
|
final Expression func = node.arguments.positional[0];
|
||||||
|
@ -246,15 +269,10 @@ class _FfiUseSiteTransformer extends FfiTransformer {
|
||||||
// We need to replace calls to 'DynamicLibrary.lookupFunction' with explicit
|
// We need to replace calls to 'DynamicLibrary.lookupFunction' with explicit
|
||||||
// Kernel, because we cannot have a generic call to 'asFunction' in its body.
|
// Kernel, because we cannot have a generic call to 'asFunction' in its body.
|
||||||
//
|
//
|
||||||
// Below, in 'visitMethodInvocation', we ensure that the type arguments to
|
// Above, in 'visitStaticInvocation', we ensure that the type arguments to
|
||||||
// 'lookupFunction' are constants, so by inlining the call to 'asFunction' at
|
// 'lookupFunction' are constants, so by inlining the call to 'asFunction' at
|
||||||
// the call-site, we ensure that there are no generic calls to 'asFunction'.
|
// the call-site, we ensure that there are no generic calls to 'asFunction'.
|
||||||
//
|
Expression _replaceLookupFunction(StaticInvocation node) {
|
||||||
// We will not detect dynamic invocations of 'asFunction' and
|
|
||||||
// 'lookupFunction': these are handled by the stubs in 'ffi_patch.dart' and
|
|
||||||
// 'dynamic_library_patch.dart'. Dynamic invocations of 'lookupFunction' (and
|
|
||||||
// 'asFunction') are not legal and throw a runtime exception.
|
|
||||||
Expression _replaceLookupFunction(MethodInvocation node) {
|
|
||||||
// The generated code looks like:
|
// The generated code looks like:
|
||||||
//
|
//
|
||||||
// _asFunctionInternal<DS, NS>(lookup<NativeFunction<NS>>(symbolName))
|
// _asFunctionInternal<DS, NS>(lookup<NativeFunction<NS>>(symbolName))
|
||||||
|
@ -263,13 +281,16 @@ class _FfiUseSiteTransformer extends FfiTransformer {
|
||||||
final DartType dartSignature = node.arguments.types[1];
|
final DartType dartSignature = node.arguments.types[1];
|
||||||
|
|
||||||
final Arguments args = Arguments([
|
final Arguments args = Arguments([
|
||||||
node.arguments.positional.single
|
node.arguments.positional[1]
|
||||||
], types: [
|
], types: [
|
||||||
InterfaceType(nativeFunctionClass, Nullability.legacy, [nativeSignature])
|
InterfaceType(nativeFunctionClass, Nullability.legacy, [nativeSignature])
|
||||||
]);
|
]);
|
||||||
|
|
||||||
final Expression lookupResult = MethodInvocation(
|
final Expression lookupResult = MethodInvocation(
|
||||||
node.receiver, Name("lookup"), args, libraryLookupMethod);
|
node.arguments.positional[0],
|
||||||
|
Name("lookup"),
|
||||||
|
args,
|
||||||
|
libraryLookupMethod);
|
||||||
|
|
||||||
return StaticInvocation(asFunctionInternal,
|
return StaticInvocation(asFunctionInternal,
|
||||||
Arguments([lookupResult], types: [dartSignature, nativeSignature]));
|
Arguments([lookupResult], types: [dartSignature, nativeSignature]));
|
||||||
|
@ -318,35 +339,7 @@ class _FfiUseSiteTransformer extends FfiTransformer {
|
||||||
|
|
||||||
final Member target = node.interfaceTarget;
|
final Member target = node.interfaceTarget;
|
||||||
try {
|
try {
|
||||||
// We will not detect dynamic invocations of 'asFunction' and
|
if (target == elementAtMethod) {
|
||||||
// 'lookupFunction' -- these are handled by the 'asFunctionInternal' stub
|
|
||||||
// in 'dynamic_library_patch.dart'. Dynamic invocations of 'asFunction'
|
|
||||||
// and 'lookupFunction' are not legal and throw a runtime exception.
|
|
||||||
if (target == lookupFunctionMethod) {
|
|
||||||
final DartType nativeType = InterfaceType(
|
|
||||||
nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
|
|
||||||
final DartType dartType = node.arguments.types[1];
|
|
||||||
|
|
||||||
_ensureNativeTypeValid(nativeType, node);
|
|
||||||
_ensureNativeTypeToDartType(nativeType, dartType, node);
|
|
||||||
return _replaceLookupFunction(node);
|
|
||||||
} else if (target == asFunctionMethod) {
|
|
||||||
final DartType dartType = node.arguments.types[0];
|
|
||||||
final DartType pointerType =
|
|
||||||
node.receiver.getStaticType(_staticTypeContext);
|
|
||||||
final DartType nativeType = _pointerTypeGetTypeArg(pointerType);
|
|
||||||
|
|
||||||
_ensureNativeTypeValid(pointerType, node);
|
|
||||||
_ensureNativeTypeValid(nativeType, node);
|
|
||||||
_ensureNativeTypeToDartType(nativeType, dartType, node);
|
|
||||||
|
|
||||||
final DartType nativeSignature =
|
|
||||||
(nativeType as InterfaceType).typeArguments[0];
|
|
||||||
return StaticInvocation(asFunctionInternal,
|
|
||||||
Arguments([node.receiver], types: [dartType, nativeSignature]));
|
|
||||||
} else if (target == elementAtMethod) {
|
|
||||||
// TODO(37773): When moving to extension methods we can get rid of
|
|
||||||
// this rewiring.
|
|
||||||
final DartType pointerType =
|
final DartType pointerType =
|
||||||
node.receiver.getStaticType(_staticTypeContext);
|
node.receiver.getStaticType(_staticTypeContext);
|
||||||
final DartType nativeType = _pointerTypeGetTypeArg(pointerType);
|
final DartType nativeType = _pointerTypeGetTypeArg(pointerType);
|
||||||
|
|
|
@ -884,7 +884,8 @@ Fragment BaseFlowGraphBuilder::AllocateObject(TokenPosition position,
|
||||||
|
|
||||||
Fragment BaseFlowGraphBuilder::BuildFfiAsFunctionInternalCall(
|
Fragment BaseFlowGraphBuilder::BuildFfiAsFunctionInternalCall(
|
||||||
const TypeArguments& signatures) {
|
const TypeArguments& signatures) {
|
||||||
ASSERT(signatures.IsInstantiated() && signatures.Length() == 2);
|
ASSERT(signatures.IsInstantiated());
|
||||||
|
ASSERT(signatures.Length() == 2);
|
||||||
|
|
||||||
const AbstractType& dart_type = AbstractType::Handle(signatures.TypeAt(0));
|
const AbstractType& dart_type = AbstractType::Handle(signatures.TypeAt(0));
|
||||||
const AbstractType& native_type = AbstractType::Handle(signatures.TypeAt(1));
|
const AbstractType& native_type = AbstractType::Handle(signatures.TypeAt(1));
|
||||||
|
|
|
@ -32,15 +32,6 @@ class DynamicLibrary {
|
||||||
Pointer<T> lookup<T extends NativeType>(String symbolName)
|
Pointer<T> lookup<T extends NativeType>(String symbolName)
|
||||||
native "Ffi_dl_lookup";
|
native "Ffi_dl_lookup";
|
||||||
|
|
||||||
// The real implementation of this function lives in FfiUseSiteTransformer
|
|
||||||
// for interface calls. Only dynamic calls (which are illegal) reach this
|
|
||||||
// implementation.
|
|
||||||
@patch
|
|
||||||
F lookupFunction<T extends Function, F extends Function>(String symbolName) {
|
|
||||||
throw UnsupportedError(
|
|
||||||
"Dynamic invocation of lookupFunction is not supported.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(dacoharkes): Expose this to users, or extend Pointer?
|
// TODO(dacoharkes): Expose this to users, or extend Pointer?
|
||||||
// https://github.com/dart-lang/sdk/issues/35881
|
// https://github.com/dart-lang/sdk/issues/35881
|
||||||
int getHandle() native "Ffi_dl_getHandle";
|
int getHandle() native "Ffi_dl_getHandle";
|
||||||
|
@ -59,3 +50,10 @@ class DynamicLibrary {
|
||||||
@patch
|
@patch
|
||||||
Pointer<Void> get handle => Pointer.fromAddress(getHandle());
|
Pointer<Void> get handle => Pointer.fromAddress(getHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension LibraryExtension on DynamicLibrary {
|
||||||
|
@patch
|
||||||
|
DS lookupFunction<NS extends Function, DS extends Function>(
|
||||||
|
String symbolName) =>
|
||||||
|
throw UnsupportedError("The body is inlined in the frontend.");
|
||||||
|
}
|
||||||
|
|
|
@ -106,11 +106,6 @@ class Pointer<T extends NativeType> {
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
Pointer<U> cast<U extends NativeType>() => Pointer.fromAddress(address);
|
Pointer<U> cast<U extends NativeType>() => Pointer.fromAddress(address);
|
||||||
|
|
||||||
@patch
|
|
||||||
R asFunction<R extends Function>() {
|
|
||||||
throw UnsupportedError("Pointer.asFunction cannot be called dynamically.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an integer encoding the ABI used for size and alignment
|
/// Returns an integer encoding the ABI used for size and alignment
|
||||||
|
@ -229,6 +224,13 @@ Pointer<Pointer<S>> _elementAtPointer<S extends NativeType>(
|
||||||
Pointer<Pointer<S>> pointer, int index) =>
|
Pointer<Pointer<S>> pointer, int index) =>
|
||||||
Pointer.fromAddress(pointer.address + _intPtrSize * index);
|
Pointer.fromAddress(pointer.address + _intPtrSize * index);
|
||||||
|
|
||||||
|
extension NativeFunctionPointer<NF extends Function>
|
||||||
|
on Pointer<NativeFunction<NF>> {
|
||||||
|
@patch
|
||||||
|
DF asFunction<DF extends Function>() =>
|
||||||
|
throw UnsupportedError("The body is inlined in the frontend.");
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// The following code is generated, do not edit by hand.
|
// The following code is generated, do not edit by hand.
|
||||||
//
|
//
|
||||||
|
|
|
@ -30,10 +30,6 @@ class DynamicLibrary {
|
||||||
/// Throws an [ArgumentError] if it fails to lookup the symbol.
|
/// Throws an [ArgumentError] if it fails to lookup the symbol.
|
||||||
external Pointer<T> lookup<T extends NativeType>(String symbolName);
|
external Pointer<T> lookup<T extends NativeType>(String symbolName);
|
||||||
|
|
||||||
/// Helper that combines lookup and cast to a Dart function.
|
|
||||||
external F lookupFunction<T extends Function, F extends Function>(
|
|
||||||
String symbolName);
|
|
||||||
|
|
||||||
/// Dynamic libraries are equal if they load the same library.
|
/// Dynamic libraries are equal if they load the same library.
|
||||||
external bool operator ==(other);
|
external bool operator ==(other);
|
||||||
|
|
||||||
|
@ -43,3 +39,10 @@ class DynamicLibrary {
|
||||||
/// The handle to the dynamic library.
|
/// The handle to the dynamic library.
|
||||||
external Pointer<Void> get handle;
|
external Pointer<Void> get handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Methods which cannot be invoked dynamically.
|
||||||
|
extension LibraryExtension on DynamicLibrary {
|
||||||
|
/// Helper that combines lookup and cast to a Dart function.
|
||||||
|
external F lookupFunction<T extends Function, F extends Function>(
|
||||||
|
String symbolName);
|
||||||
|
}
|
||||||
|
|
|
@ -68,13 +68,6 @@ class Pointer<T extends NativeType> extends NativeType {
|
||||||
/// Cast Pointer<T> to a Pointer<V>.
|
/// Cast Pointer<T> to a Pointer<V>.
|
||||||
external Pointer<U> cast<U extends NativeType>();
|
external Pointer<U> cast<U extends NativeType>();
|
||||||
|
|
||||||
/// Convert to Dart function, automatically marshalling the arguments
|
|
||||||
/// and return value.
|
|
||||||
///
|
|
||||||
/// Can only be called on [Pointer]<[NativeFunction]>. Does not accept dynamic
|
|
||||||
/// invocations -- where the type of the receiver is [dynamic].
|
|
||||||
external R asFunction<@DartRepresentationOf("T") R extends Function>();
|
|
||||||
|
|
||||||
/// Equality for Pointers only depends on their address.
|
/// Equality for Pointers only depends on their address.
|
||||||
bool operator ==(other) {
|
bool operator ==(other) {
|
||||||
if (other == null) return false;
|
if (other == null) return false;
|
||||||
|
@ -87,6 +80,14 @@ class Pointer<T extends NativeType> extends NativeType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extension on [Pointer] specialized for the type argument [NativeFunction].
|
||||||
|
extension NativeFunctionPointer<NF extends Function>
|
||||||
|
on Pointer<NativeFunction<NF>> {
|
||||||
|
/// Convert to Dart function, automatically marshalling the arguments
|
||||||
|
/// and return value.
|
||||||
|
external DF asFunction<@DartRepresentationOf("NF") DF extends Function>();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// The following code is generated, do not edit by hand.
|
// The following code is generated, do not edit by hand.
|
||||||
//
|
//
|
||||||
|
|
|
@ -30,15 +30,6 @@ class DynamicLibrary {
|
||||||
Pointer<T> lookup<T extends NativeType>(String symbolName)
|
Pointer<T> lookup<T extends NativeType>(String symbolName)
|
||||||
native "Ffi_dl_lookup";
|
native "Ffi_dl_lookup";
|
||||||
|
|
||||||
// The real implementation of this function lives in FfiUseSiteTransformer
|
|
||||||
// for interface calls. Only dynamic calls (which are illegal) reach this
|
|
||||||
// implementation.
|
|
||||||
@patch
|
|
||||||
F lookupFunction<T extends Function, F extends Function>(String symbolName) {
|
|
||||||
throw UnsupportedError(
|
|
||||||
"Dynamic invocation of lookupFunction is not supported.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(dacoharkes): Expose this to users, or extend Pointer?
|
// TODO(dacoharkes): Expose this to users, or extend Pointer?
|
||||||
// https://github.com/dart-lang/sdk/issues/35881
|
// https://github.com/dart-lang/sdk/issues/35881
|
||||||
int getHandle() native "Ffi_dl_getHandle";
|
int getHandle() native "Ffi_dl_getHandle";
|
||||||
|
@ -58,3 +49,10 @@ class DynamicLibrary {
|
||||||
@patch
|
@patch
|
||||||
Pointer<Void> get handle => Pointer.fromAddress(getHandle());
|
Pointer<Void> get handle => Pointer.fromAddress(getHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension LibraryExtension on DynamicLibrary {
|
||||||
|
@patch
|
||||||
|
DS lookupFunction<NS extends Function, DS extends Function>(
|
||||||
|
String symbolName) =>
|
||||||
|
throw UnsupportedError("The body is inlined in the frontend.");
|
||||||
|
}
|
||||||
|
|
|
@ -104,11 +104,6 @@ class Pointer<T extends NativeType> {
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
Pointer<U> cast<U extends NativeType>() => Pointer.fromAddress(address);
|
Pointer<U> cast<U extends NativeType>() => Pointer.fromAddress(address);
|
||||||
|
|
||||||
@patch
|
|
||||||
R asFunction<R extends Function>() {
|
|
||||||
throw UnsupportedError("Pointer.asFunction cannot be called dynamically.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an integer encoding the ABI used for size and alignment
|
/// Returns an integer encoding the ABI used for size and alignment
|
||||||
|
@ -227,6 +222,13 @@ Pointer<Pointer<S>> _elementAtPointer<S extends NativeType>(
|
||||||
Pointer<Pointer<S>> pointer, int index) =>
|
Pointer<Pointer<S>> pointer, int index) =>
|
||||||
Pointer.fromAddress(pointer.address + _intPtrSize * index);
|
Pointer.fromAddress(pointer.address + _intPtrSize * index);
|
||||||
|
|
||||||
|
extension NativeFunctionPointer<NF extends Function>
|
||||||
|
on Pointer<NativeFunction<NF>> {
|
||||||
|
@patch
|
||||||
|
DF asFunction<DF extends Function>() =>
|
||||||
|
throw UnsupportedError("The body is inlined in the frontend.");
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// The following code is generated, do not edit by hand.
|
// The following code is generated, do not edit by hand.
|
||||||
//
|
//
|
||||||
|
|
|
@ -28,10 +28,6 @@ class DynamicLibrary {
|
||||||
/// Throws an [ArgumentError] if it fails to lookup the symbol.
|
/// Throws an [ArgumentError] if it fails to lookup the symbol.
|
||||||
external Pointer<T> lookup<T extends NativeType>(String symbolName);
|
external Pointer<T> lookup<T extends NativeType>(String symbolName);
|
||||||
|
|
||||||
/// Helper that combines lookup and cast to a Dart function.
|
|
||||||
external F lookupFunction<T extends Function, F extends Function>(
|
|
||||||
String symbolName);
|
|
||||||
|
|
||||||
/// Dynamic libraries are equal if they load the same library.
|
/// Dynamic libraries are equal if they load the same library.
|
||||||
external bool operator ==(Object other);
|
external bool operator ==(Object other);
|
||||||
|
|
||||||
|
@ -41,3 +37,10 @@ class DynamicLibrary {
|
||||||
/// The handle to the dynamic library.
|
/// The handle to the dynamic library.
|
||||||
external Pointer<Void> get handle;
|
external Pointer<Void> get handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Methods which cannot be invoked dynamically.
|
||||||
|
extension LibraryExtension on DynamicLibrary {
|
||||||
|
/// Helper that combines lookup and cast to a Dart function.
|
||||||
|
external F lookupFunction<T extends Function, F extends Function>(
|
||||||
|
String symbolName);
|
||||||
|
}
|
||||||
|
|
|
@ -66,13 +66,6 @@ class Pointer<T extends NativeType> extends NativeType {
|
||||||
/// Cast Pointer<T> to a Pointer<V>.
|
/// Cast Pointer<T> to a Pointer<V>.
|
||||||
external Pointer<U> cast<U extends NativeType>();
|
external Pointer<U> cast<U extends NativeType>();
|
||||||
|
|
||||||
/// Convert to Dart function, automatically marshalling the arguments
|
|
||||||
/// and return value.
|
|
||||||
///
|
|
||||||
/// Can only be called on [Pointer]<[NativeFunction]>. Does not accept dynamic
|
|
||||||
/// invocations -- where the type of the receiver is [dynamic].
|
|
||||||
external R asFunction<@DartRepresentationOf("T") R extends Function>();
|
|
||||||
|
|
||||||
/// Equality for Pointers only depends on their address.
|
/// Equality for Pointers only depends on their address.
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
if (other is! Pointer) return false;
|
if (other is! Pointer) return false;
|
||||||
|
@ -86,6 +79,14 @@ class Pointer<T extends NativeType> extends NativeType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extension on [Pointer] specialized for the type argument [NativeFunction].
|
||||||
|
extension NativeFunctionPointer<NF extends Function>
|
||||||
|
on Pointer<NativeFunction<NF>> {
|
||||||
|
/// Convert to Dart function, automatically marshalling the arguments
|
||||||
|
/// and return value.
|
||||||
|
external DF asFunction<@DartRepresentationOf("NF") DF extends Function>();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// The following code is generated, do not edit by hand.
|
// The following code is generated, do not edit by hand.
|
||||||
//
|
//
|
||||||
|
|
|
@ -68,7 +68,7 @@ void testWrongTypes() {
|
||||||
// an exception.
|
// an exception.
|
||||||
void testDynamicAsFunction() {
|
void testDynamicAsFunction() {
|
||||||
dynamic x = ffi.nullptr.cast<ffi.NativeFunction<ffi.Void Function()>>();
|
dynamic x = ffi.nullptr.cast<ffi.NativeFunction<ffi.Void Function()>>();
|
||||||
Expect.throwsUnsupportedError(() {
|
Expect.throwsNoSuchMethodError(() {
|
||||||
x.asFunction<void Function()>();
|
x.asFunction<void Function()>();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ void testDynamicAsFunction() {
|
||||||
// type throws an exception.
|
// type throws an exception.
|
||||||
void testDynamicLookupFunction() {
|
void testDynamicLookupFunction() {
|
||||||
dynamic lib = ffiTestFunctions;
|
dynamic lib = ffiTestFunctions;
|
||||||
Expect.throwsUnsupportedError(() {
|
Expect.throwsNoSuchMethodError(() {
|
||||||
lib.lookupFunction<ffi.Void Function(), void Function()>("_");
|
lib.lookupFunction<ffi.Void Function(), void Function()>("_");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ void testWrongTypes() {
|
||||||
// an exception.
|
// an exception.
|
||||||
void testDynamicAsFunction() {
|
void testDynamicAsFunction() {
|
||||||
dynamic x = ffi.nullptr.cast<ffi.NativeFunction<ffi.Void Function()>>();
|
dynamic x = ffi.nullptr.cast<ffi.NativeFunction<ffi.Void Function()>>();
|
||||||
Expect.throwsUnsupportedError(() {
|
Expect.throwsNoSuchMethodError(() {
|
||||||
x.asFunction<void Function()>();
|
x.asFunction<void Function()>();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ void testDynamicAsFunction() {
|
||||||
// type throws an exception.
|
// type throws an exception.
|
||||||
void testDynamicLookupFunction() {
|
void testDynamicLookupFunction() {
|
||||||
dynamic lib = ffiTestFunctions;
|
dynamic lib = ffiTestFunctions;
|
||||||
Expect.throwsUnsupportedError(() {
|
Expect.throwsNoSuchMethodError(() {
|
||||||
lib.lookupFunction<ffi.Void Function(), void Function()>("_");
|
lib.lookupFunction<ffi.Void Function(), void Function()>("_");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue