diff --git a/runtime/lib/ffi_dynamic_library.cc b/runtime/lib/ffi_dynamic_library.cc index b083e04e390..68ec283019b 100644 --- a/runtime/lib/ffi_dynamic_library.cc +++ b/runtime/lib/ffi_dynamic_library.cc @@ -19,51 +19,14 @@ namespace dart { -// Concatenates a NULL terminated array of strings. -// The returned string is scope allocated. -// TODO(dacoharkes): Can we share this with runtime/bin/extensions.cc? -const char* Concatenate(const char** strings) { - int size = 1; // null termination. - for (int i = 0; strings[i] != NULL; i++) { - size += strlen(strings[i]); - } - char* result = reinterpret_cast(Dart_ScopeAllocate(size)); - int index = 0; - for (int i = 0; strings[i] != NULL; i++) { - index += snprintf(result + index, size - index, "%s", strings[i]); - } - ASSERT(index == size - 1); - ASSERT(result[size - 1] == '\0'); - return result; -} - -// TODO(dacoharkes): Can we share this with runtime/bin/extensions.cc? -const char* LibraryPath(const char* library_name) { - const char* library_prefix = "lib"; -#if defined(TARGET_OS_LINUX) - const char* library_extension = "so"; -#elif defined(TARGET_OS_MACOS) - const char* library_extension = "dylib"; -#else - const char* library_extension = ""; - UNREACHABLE(); -#endif - - const char* path_components[] = { - library_prefix, library_name, ".", library_extension, NULL, - }; - - return Concatenate(path_components); -} - DEFINE_NATIVE_ENTRY(Ffi_dl_open, 0, 1) { #if !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS) UNREACHABLE(); #else - GET_NON_NULL_NATIVE_ARGUMENT(String, argName, arguments->NativeArgAt(0)); + GET_NON_NULL_NATIVE_ARGUMENT(String, lib_path, arguments->NativeArgAt(0)); dlerror(); // Clear any errors. - void* handle = dlopen(LibraryPath(argName.ToCString()), RTLD_LAZY); + void* handle = dlopen(lib_path.ToCString(), RTLD_LAZY); if (handle == nullptr) { char* error = dlerror(); const String& msg = String::Handle( diff --git a/samples/ffi/dylib_utils.dart b/samples/ffi/dylib_utils.dart new file mode 100644 index 00000000000..1929961e35f --- /dev/null +++ b/samples/ffi/dylib_utils.dart @@ -0,0 +1,18 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:ffi' as ffi; +import 'dart:io' show Platform; + +String _platformPath(String name, {String path}) { + if (path == null) path = ""; + if (Platform.isLinux) return path + "lib" + name + ".so"; + if (Platform.isMacOS) return path + "lib" + name + ".dylib"; + throw Exception("Platform not implemented"); +} + +ffi.DynamicLibrary dlopenPlatformSpecific(String name, {String path}) { + String fullPath = _platformPath(name, path: path); + return ffi.DynamicLibrary.open(fullPath); +} diff --git a/samples/ffi/sample_ffi_dynamic_library.dart b/samples/ffi/sample_ffi_dynamic_library.dart index cf834005a2d..234e3d020ab 100644 --- a/samples/ffi/sample_ffi_dynamic_library.dart +++ b/samples/ffi/sample_ffi_dynamic_library.dart @@ -4,12 +4,14 @@ import 'dart:ffi' as ffi; +import 'dylib_utils.dart'; + typedef NativeDoubleUnOp = ffi.Double Function(ffi.Double); typedef DoubleUnOp = double Function(double); main(List arguments) { - ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library"); + ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library"); print(l); print(l.runtimeType); diff --git a/samples/ffi/sample_ffi_functions.dart b/samples/ffi/sample_ffi_functions.dart index 62b5718520d..4a3cf984a67 100644 --- a/samples/ffi/sample_ffi_functions.dart +++ b/samples/ffi/sample_ffi_functions.dart @@ -4,6 +4,8 @@ import 'dart:ffi' as ffi; +import 'dylib_utils.dart'; + typedef NativeUnaryOp = ffi.Int32 Function(ffi.Int32); typedef NativeBinaryOp = ffi.Int32 Function(ffi.Int32, ffi.Int32); typedef UnaryOp = int Function(int); @@ -93,7 +95,7 @@ main(List arguments) { print('start main'); ffi.DynamicLibrary ffiTestFunctions = - ffi.DynamicLibrary.open("ffi_test_functions"); + dlopenPlatformSpecific("ffi_test_functions"); { // int32 bin op diff --git a/samples/ffi/sample_ffi_functions_callbacks.dart b/samples/ffi/sample_ffi_functions_callbacks.dart index ddd68405f5e..8549377b064 100644 --- a/samples/ffi/sample_ffi_functions_callbacks.dart +++ b/samples/ffi/sample_ffi_functions_callbacks.dart @@ -4,6 +4,8 @@ import 'dart:ffi' as ffi; +import 'dylib_utils.dart'; + import 'coordinate.dart'; typedef NativeCoordinateOp = Coordinate Function(Coordinate); @@ -33,7 +35,7 @@ main(List arguments) { print('start main'); ffi.DynamicLibrary ffiTestFunctions = - ffi.DynamicLibrary.open("ffi_test_functions"); + dlopenPlatformSpecific("ffi_test_functions"); { // pass a c pointer to a c function as an argument to a c function diff --git a/samples/ffi/sample_ffi_functions_structs.dart b/samples/ffi/sample_ffi_functions_structs.dart index ba076e007f2..d2b1e410a35 100644 --- a/samples/ffi/sample_ffi_functions_structs.dart +++ b/samples/ffi/sample_ffi_functions_structs.dart @@ -4,6 +4,8 @@ import 'dart:ffi' as ffi; +import 'dylib_utils.dart'; + import 'coordinate.dart'; typedef NativeCoordinateOp = Coordinate Function(Coordinate); @@ -12,7 +14,7 @@ main(List arguments) { print('start main'); ffi.DynamicLibrary ffiTestFunctions = - ffi.DynamicLibrary.open("ffi_test_functions"); + dlopenPlatformSpecific("ffi_test_functions"); { // pass a struct to a c function and get a struct as return value diff --git a/tests/standalone_2/ffi/dylib_utils.dart b/tests/standalone_2/ffi/dylib_utils.dart new file mode 100644 index 00000000000..1929961e35f --- /dev/null +++ b/tests/standalone_2/ffi/dylib_utils.dart @@ -0,0 +1,18 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:ffi' as ffi; +import 'dart:io' show Platform; + +String _platformPath(String name, {String path}) { + if (path == null) path = ""; + if (Platform.isLinux) return path + "lib" + name + ".so"; + if (Platform.isMacOS) return path + "lib" + name + ".dylib"; + throw Exception("Platform not implemented"); +} + +ffi.DynamicLibrary dlopenPlatformSpecific(String name, {String path}) { + String fullPath = _platformPath(name, path: path); + return ffi.DynamicLibrary.open(fullPath); +} diff --git a/tests/standalone_2/ffi/dynamic_library_test.dart b/tests/standalone_2/ffi/dynamic_library_test.dart index 1c3c45dd578..0a38e9ad0bf 100644 --- a/tests/standalone_2/ffi/dynamic_library_test.dart +++ b/tests/standalone_2/ffi/dynamic_library_test.dart @@ -8,6 +8,8 @@ library FfiTest; import 'dart:ffi' as ffi; +import 'dylib_utils.dart'; + import 'package:expect/expect.dart'; void main() { @@ -20,13 +22,13 @@ void main() { } void testOpen() { - ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library"); + ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library"); Expect.notEquals(null, l); } void testOpenError() { Expect.throws( - () => ffi.DynamicLibrary.open("doesnotexistforsurelibrary123409876")); + () => dlopenPlatformSpecific("doesnotexistforsurelibrary123409876")); } typedef NativeDoubleUnOp = ffi.Double Function(ffi.Double); @@ -34,30 +36,30 @@ typedef NativeDoubleUnOp = ffi.Double Function(ffi.Double); typedef DoubleUnOp = double Function(double); void testLookup() { - ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library"); + ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library"); var timesFour = l.lookupFunction("timesFour"); Expect.approxEquals(12.0, timesFour(3)); } void testLookupError() { - ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library"); + ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library"); Expect.throws(() => l.lookupFunction( "functionnamethatdoesnotexistforsure749237593845")); } void testToString() { - ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library"); + ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library"); Expect.stringEquals( "DynamicLibrary: handle=0x", l.toString().substring(0, 25)); } void testEquality() { - ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library"); - ffi.DynamicLibrary l2 = ffi.DynamicLibrary.open("ffi_test_dynamic_library"); + ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library"); + ffi.DynamicLibrary l2 = dlopenPlatformSpecific("ffi_test_dynamic_library"); Expect.equals(l, l2); Expect.equals(l.hashCode, l2.hashCode); Expect.notEquals(l, null); Expect.notEquals(null, l); - ffi.DynamicLibrary l3 = ffi.DynamicLibrary.open("ffi_test_functions"); + ffi.DynamicLibrary l3 = dlopenPlatformSpecific("ffi_test_functions"); Expect.notEquals(l, l3); } diff --git a/tests/standalone_2/ffi/function_callbacks_test.dart b/tests/standalone_2/ffi/function_callbacks_test.dart index 2f3212b8da1..98171829b47 100644 --- a/tests/standalone_2/ffi/function_callbacks_test.dart +++ b/tests/standalone_2/ffi/function_callbacks_test.dart @@ -8,6 +8,8 @@ library FfiTest; import 'dart:ffi' as ffi; +import 'dylib_utils.dart'; + import "package:expect/expect.dart"; import 'coordinate.dart'; @@ -24,7 +26,7 @@ void main() { } ffi.DynamicLibrary ffiTestFunctions = - ffi.DynamicLibrary.open("ffi_test_functions"); + dlopenPlatformSpecific("ffi_test_functions"); /// pass a pointer to a c function as an argument to a c function void testFunctionWithFunctionPointer() { diff --git a/tests/standalone_2/ffi/function_structs_test.dart b/tests/standalone_2/ffi/function_structs_test.dart index 6f74a90bbd4..ce7bd1186cb 100644 --- a/tests/standalone_2/ffi/function_structs_test.dart +++ b/tests/standalone_2/ffi/function_structs_test.dart @@ -9,6 +9,8 @@ library FfiTest; import 'dart:ffi' as ffi; +import 'dylib_utils.dart'; + import "package:expect/expect.dart"; import 'coordinate.dart'; @@ -23,7 +25,7 @@ void main() { } ffi.DynamicLibrary ffiTestFunctions = - ffi.DynamicLibrary.open("ffi_test_functions"); + dlopenPlatformSpecific("ffi_test_functions"); /// pass a struct to a c function and get a struct as return value void testFunctionWithStruct() { diff --git a/tests/standalone_2/ffi/function_test.dart b/tests/standalone_2/ffi/function_test.dart index bed0264b025..dacce5ddf3e 100644 --- a/tests/standalone_2/ffi/function_test.dart +++ b/tests/standalone_2/ffi/function_test.dart @@ -8,6 +8,8 @@ library FfiTest; import 'dart:ffi' as ffi; +import 'dylib_utils.dart'; + import "package:expect/expect.dart"; void main() { @@ -29,7 +31,7 @@ void main() { } ffi.DynamicLibrary ffiTestFunctions = - ffi.DynamicLibrary.open("ffi_test_functions"); + dlopenPlatformSpecific("ffi_test_functions"); typedef NativeBinaryOp = ffi.Int32 Function(ffi.Int32, ffi.Int32); typedef UnaryOp = int Function(int); diff --git a/tests/standalone_2/ffi/static_checks_test.dart b/tests/standalone_2/ffi/static_checks_test.dart index 422fc6f97a6..15e162a97b0 100644 --- a/tests/standalone_2/ffi/static_checks_test.dart +++ b/tests/standalone_2/ffi/static_checks_test.dart @@ -8,6 +8,8 @@ library FfiTest; import 'dart:ffi' as ffi; +import 'dylib_utils.dart'; + void main() { testGetGeneric(); testGetGeneric2(); @@ -245,7 +247,7 @@ void testFromFunctionTearOff() { void testLookupFunctionGeneric() { Function generic() { - ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library"); + ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library"); Function result; result = l.lookupFunction("cos"); //# 15: compile-time error return result; @@ -256,7 +258,7 @@ void testLookupFunctionGeneric() { void testLookupFunctionGeneric2() { Function generic() { - ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library"); + ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library"); Function result; result = //# 16: compile-time error l.lookupFunction("cos"); //# 16: compile-time error @@ -267,12 +269,12 @@ void testLookupFunctionGeneric2() { } void testLookupFunctionWrongNativeFunctionSignature() { - ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library"); + ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library"); l.lookupFunction("cos"); //# 17: compile-time error } void testLookupFunctionTypeMismatch() { - ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library"); + ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library"); l.lookupFunction("cos"); //# 18: compile-time error }