diff --git a/pkg/vm/lib/transformations/ffi_native.dart b/pkg/vm/lib/transformations/ffi_native.dart index 8d441c1123c..3d44d461be2 100644 --- a/pkg/vm/lib/transformations/ffi_native.dart +++ b/pkg/vm/lib/transformations/ffi_native.dart @@ -102,22 +102,26 @@ class FfiNativeTransformer extends Transformer { final DartType dartType = node.function.computeThisFunctionType(Nullability.nonNullable); // Double Function(Double) - final nativeType = annotationConst.typeArguments[0]; + final nativeType = annotationConst.typeArguments[0] as FunctionType; // InterfaceType(NativeFunction*) final DartType nativeInterfaceType = InterfaceType(nativeFunctionClass, Nullability.legacy, [nativeType]); + // Derive number of arguments from the native function signature. + final args_n = nativeType.positionalParameters.length; + // TODO(dartbug.com/31579): Add `..fileOffset`s once we can handle these in // patch files. - // _ffi_resolver('dart:math', 'Math_sqrt') + // _ffi_resolver('dart:math', 'Math_sqrt', 1) final resolverInvocation = FunctionInvocation( FunctionAccessKind.FunctionType, StaticGet(resolverField), Arguments([ ConstantExpression( StringConstant(currentLibrary!.importUri.toString())), - ConstantExpression(functionName) + ConstantExpression(functionName), + ConstantExpression(IntConstant(args_n)), ]), functionType: resolverField.type as FunctionType); diff --git a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc index adcdc07a052..affbe3ae920 100644 --- a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc +++ b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc @@ -1094,11 +1094,11 @@ intptr_t ReturnIntPtr(intptr_t x) { return x; } -static void* FfiNativeResolver(const char* name) { - if (strcmp(name, "ReturnIntPtr") == 0) { +static void* FfiNativeResolver(const char* name, uintptr_t args_n) { + if (strcmp(name, "ReturnIntPtr") == 0 && args_n == 1) { return reinterpret_cast(ReturnIntPtr); } - if (strcmp(name, "IsThreadInGenerated") == 0) { + if (strcmp(name, "IsThreadInGenerated") == 0 && args_n == 0) { return reinterpret_cast(IsThreadInGenerated); } // This should be unreachable in tests. diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h index 861a87f27f3..422e2be38e3 100644 --- a/runtime/include/dart_api.h +++ b/runtime/include/dart_api.h @@ -3046,7 +3046,7 @@ typedef const uint8_t* (*Dart_NativeEntrySymbol)(Dart_NativeFunction nf); * * See Dart_SetFfiNativeResolver. */ -typedef void* (*Dart_FfiNativeResolver)(const char* name); +typedef void* (*Dart_FfiNativeResolver)(const char* name, uintptr_t args_n); /* * =========== diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc index cc4a6ff5203..239f75863cd 100644 --- a/runtime/lib/ffi.cc +++ b/runtime/lib/ffi.cc @@ -276,7 +276,9 @@ DEFINE_NATIVE_ENTRY(DartApiDLInitializeData, 0, 0) { } // FFI native C function pointer resolver. -static intptr_t FfiResolve(Dart_Handle lib_url, Dart_Handle name) { +static intptr_t FfiResolve(Dart_Handle lib_url, + Dart_Handle name, + uintptr_t args_n) { DARTSCOPE(Thread::Current()); const String& lib_url_str = Api::UnwrapStringHandle(T->zone(), lib_url); @@ -296,7 +298,7 @@ static intptr_t FfiResolve(Dart_Handle lib_url, Dart_Handle name) { Exceptions::ThrowArgumentError(error); } - auto* f = resolver(function_name.ToCString()); + auto* f = resolver(function_name.ToCString(), args_n); if (f == nullptr) { const String& error = String::Handle(String::NewFormatted( "Couldn't resolve function: '%s'.", function_name.ToCString())); diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc index 2849c6b5d37..4d9d1df5095 100644 --- a/runtime/vm/dart_api_impl_test.cc +++ b/runtime/vm/dart_api_impl_test.cc @@ -9585,8 +9585,9 @@ static intptr_t EchoInt(double x) { return x; } -static void* FfiNativeResolver(const char* name) { +static void* FfiNativeResolver(const char* name, uintptr_t args_n) { ASSERT(strcmp(name, "EchoInt") == 0); + ASSERT(args_n == 1); return reinterpret_cast(EchoInt); } @@ -9628,7 +9629,7 @@ TEST_CASE(Dart_SetFfiNativeResolver_MissingResolver) { "Invalid argument(s): Library has no handler: 'file:///test-lib'."); } -static void* NopResolver(const char* name) { +static void* NopResolver(const char* name, uintptr_t args_n) { return nullptr; } diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart index 2e3b2bd5513..3e2dd21aa99 100644 --- a/sdk/lib/ffi/ffi.dart +++ b/sdk/lib/ffi/ffi.dart @@ -824,11 +824,11 @@ class FfiNative { // Bootstrapping native for getting the FFI native C function pointer to look // up the FFI resolver. @pragma("vm:external-name", "Ffi_GetFfiNativeResolver") -external Pointer> +external Pointer> _get_ffi_native_resolver(); // Resolver for FFI Native C function pointers. @pragma('vm:entry-point') -final _ffi_resolver = - _get_ffi_native_resolver>() - .asFunction(); +final _ffi_resolver = _get_ffi_native_resolver< + NativeFunction>() + .asFunction();