mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[vm/ffi] DynamicLibrary.process() and DynamicLibrary.executable()
Change-Id: I6be84f24f0ac245ba176748e4a3ec1ba782798ce Cq-Include-Trybots: luci.dart.try:vm-kernel-win-debug-x64-try,vm-kernel-mac-debug-x64-try,vm-ffi-android-debug-arm-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/113687 Commit-Queue: Samir Jindel <sjindel@google.com> Reviewed-by: Daco Harkes <dacoharkes@google.com>
This commit is contained in:
parent
2891ec679b
commit
e64738ffbc
|
@ -36,14 +36,20 @@ static void* LoadExtensionLibrary(const char* library_file) {
|
|||
#elif defined(HOST_OS_WINDOWS)
|
||||
SetLastError(0); // Clear any errors.
|
||||
|
||||
// Convert to wchar_t string.
|
||||
const int name_len =
|
||||
MultiByteToWideChar(CP_UTF8, 0, library_file, -1, NULL, 0);
|
||||
wchar_t* name = new wchar_t[name_len];
|
||||
MultiByteToWideChar(CP_UTF8, 0, library_file, -1, name, name_len);
|
||||
void* ext;
|
||||
|
||||
void* ext = LoadLibraryW(name);
|
||||
delete[] name;
|
||||
if (library_file == nullptr) {
|
||||
ext = GetModuleHandle(nullptr);
|
||||
} else {
|
||||
// Convert to wchar_t string.
|
||||
const int name_len =
|
||||
MultiByteToWideChar(CP_UTF8, 0, library_file, -1, NULL, 0);
|
||||
wchar_t* name = new wchar_t[name_len];
|
||||
MultiByteToWideChar(CP_UTF8, 0, library_file, -1, name, name_len);
|
||||
|
||||
ext = LoadLibraryW(name);
|
||||
delete[] name;
|
||||
}
|
||||
|
||||
if (ext == nullptr) {
|
||||
const int error = GetLastError();
|
||||
|
@ -70,6 +76,22 @@ DEFINE_NATIVE_ENTRY(Ffi_dl_open, 0, 1) {
|
|||
return DynamicLibrary::New(handle);
|
||||
}
|
||||
|
||||
DEFINE_NATIVE_ENTRY(Ffi_dl_processLibrary, 0, 0) {
|
||||
#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || defined(HOST_OS_ANDROID)
|
||||
return DynamicLibrary::New(RTLD_DEFAULT);
|
||||
#else
|
||||
const Array& args = Array::Handle(Array::New(1));
|
||||
args.SetAt(0,
|
||||
String::Handle(String::New(
|
||||
"DynamicLibrary.process is not available on this platform.")));
|
||||
Exceptions::ThrowByType(Exceptions::kUnsupported, args);
|
||||
#endif
|
||||
}
|
||||
|
||||
DEFINE_NATIVE_ENTRY(Ffi_dl_executableLibrary, 0, 0) {
|
||||
return DynamicLibrary::New(LoadExtensionLibrary(nullptr));
|
||||
}
|
||||
|
||||
static void* ResolveSymbol(void* handle, const char* symbol) {
|
||||
#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || defined(HOST_OS_ANDROID)
|
||||
dlerror(); // Clear any errors.
|
||||
|
|
|
@ -8,6 +8,8 @@ import "dart:_internal" show patch;
|
|||
import 'dart:typed_data' show TypedData;
|
||||
|
||||
DynamicLibrary _open(String name) native "Ffi_dl_open";
|
||||
DynamicLibrary _processLibrary() native "Ffi_dl_processLibrary";
|
||||
DynamicLibrary _executableLibrary() native "Ffi_dl_executableLibrary";
|
||||
|
||||
@patch
|
||||
@pragma("vm:entry-point")
|
||||
|
@ -17,6 +19,12 @@ class DynamicLibrary {
|
|||
return _open(name);
|
||||
}
|
||||
|
||||
@patch
|
||||
factory DynamicLibrary.process() => _processLibrary();
|
||||
|
||||
@patch
|
||||
factory DynamicLibrary.executable() => _executableLibrary();
|
||||
|
||||
@patch
|
||||
Pointer<T> lookup<T extends NativeType>(String symbolName)
|
||||
native "Ffi_dl_lookup";
|
||||
|
|
|
@ -389,6 +389,8 @@ namespace dart {
|
|||
V(Ffi_dl_lookup, 2) \
|
||||
V(Ffi_dl_getHandle, 1) \
|
||||
V(Ffi_asExternalTypedData, 2) \
|
||||
V(Ffi_dl_processLibrary, 0) \
|
||||
V(Ffi_dl_executableLibrary, 0) \
|
||||
V(TransferableTypedData_factory, 2) \
|
||||
V(TransferableTypedData_materialize, 1)
|
||||
|
||||
|
|
|
@ -6,11 +6,20 @@ part of dart.ffi;
|
|||
|
||||
/// Represents a dynamically loaded C library.
|
||||
class DynamicLibrary {
|
||||
/// Loads a dynamic library file. This is the equivalent of dlopen.
|
||||
/// Creates a dynamic library holding all global symbols.
|
||||
///
|
||||
/// Any symbol in a library currently loaded with global visibility (including
|
||||
/// the executable itself) may be resolved in this library.
|
||||
///
|
||||
/// This feature is not available on Windows, instead an exception is thrown.
|
||||
external factory DynamicLibrary.process();
|
||||
|
||||
/// Creates a dynamic library representing the running executable.
|
||||
external factory DynamicLibrary.executable();
|
||||
|
||||
/// Loads a dynamic library file with local visibility.
|
||||
///
|
||||
/// Throws an [ArgumentError] if loading the dynamic library fails.
|
||||
///
|
||||
/// Note that it loads the functions in the library lazily (RTLD_LAZY).
|
||||
external factory DynamicLibrary.open(String name);
|
||||
|
||||
/// Looks up a symbol in the [DynamicLibrary] and returns its address in
|
||||
|
|
|
@ -8,12 +8,13 @@
|
|||
|
||||
library FfiTest;
|
||||
|
||||
import 'dart:io';
|
||||
import 'dart:ffi';
|
||||
|
||||
import 'dylib_utils.dart';
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
import 'dylib_utils.dart';
|
||||
|
||||
void main() {
|
||||
testOpen();
|
||||
testOpenError();
|
||||
|
@ -42,6 +43,20 @@ void testLookup() {
|
|||
DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
|
||||
var timesFour = l.lookupFunction<NativeDoubleUnOp, DoubleUnOp>("timesFour");
|
||||
Expect.approxEquals(12.0, timesFour(3));
|
||||
|
||||
if (Platform.isMacOS ||
|
||||
Platform.isIOS ||
|
||||
Platform.isAndroid ||
|
||||
Platform.isLinux) {
|
||||
// Lookup a symbol from 'libc' since it's loaded with global visibility.
|
||||
DynamicLibrary p = DynamicLibrary.process();
|
||||
Expect.isTrue(p.lookup<Void>("strcmp") != nullptr);
|
||||
} else {
|
||||
Expect.throws<UnsupportedError>(() => DynamicLibrary.process());
|
||||
}
|
||||
|
||||
DynamicLibrary e = DynamicLibrary.executable();
|
||||
Expect.isTrue(e.lookup("Dart_Invoke") != nullptr);
|
||||
}
|
||||
|
||||
void testLookupError() {
|
||||
|
|
Loading…
Reference in a new issue