mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:39:48 +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)
|
#elif defined(HOST_OS_WINDOWS)
|
||||||
SetLastError(0); // Clear any errors.
|
SetLastError(0); // Clear any errors.
|
||||||
|
|
||||||
// Convert to wchar_t string.
|
void* ext;
|
||||||
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 = LoadLibraryW(name);
|
if (library_file == nullptr) {
|
||||||
delete[] name;
|
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) {
|
if (ext == nullptr) {
|
||||||
const int error = GetLastError();
|
const int error = GetLastError();
|
||||||
|
@ -70,6 +76,22 @@ DEFINE_NATIVE_ENTRY(Ffi_dl_open, 0, 1) {
|
||||||
return DynamicLibrary::New(handle);
|
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) {
|
static void* ResolveSymbol(void* handle, const char* symbol) {
|
||||||
#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || defined(HOST_OS_ANDROID)
|
#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || defined(HOST_OS_ANDROID)
|
||||||
dlerror(); // Clear any errors.
|
dlerror(); // Clear any errors.
|
||||||
|
|
|
@ -8,6 +8,8 @@ import "dart:_internal" show patch;
|
||||||
import 'dart:typed_data' show TypedData;
|
import 'dart:typed_data' show TypedData;
|
||||||
|
|
||||||
DynamicLibrary _open(String name) native "Ffi_dl_open";
|
DynamicLibrary _open(String name) native "Ffi_dl_open";
|
||||||
|
DynamicLibrary _processLibrary() native "Ffi_dl_processLibrary";
|
||||||
|
DynamicLibrary _executableLibrary() native "Ffi_dl_executableLibrary";
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
@pragma("vm:entry-point")
|
@pragma("vm:entry-point")
|
||||||
|
@ -17,6 +19,12 @@ class DynamicLibrary {
|
||||||
return _open(name);
|
return _open(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@patch
|
||||||
|
factory DynamicLibrary.process() => _processLibrary();
|
||||||
|
|
||||||
|
@patch
|
||||||
|
factory DynamicLibrary.executable() => _executableLibrary();
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
Pointer<T> lookup<T extends NativeType>(String symbolName)
|
Pointer<T> lookup<T extends NativeType>(String symbolName)
|
||||||
native "Ffi_dl_lookup";
|
native "Ffi_dl_lookup";
|
||||||
|
|
|
@ -389,6 +389,8 @@ namespace dart {
|
||||||
V(Ffi_dl_lookup, 2) \
|
V(Ffi_dl_lookup, 2) \
|
||||||
V(Ffi_dl_getHandle, 1) \
|
V(Ffi_dl_getHandle, 1) \
|
||||||
V(Ffi_asExternalTypedData, 2) \
|
V(Ffi_asExternalTypedData, 2) \
|
||||||
|
V(Ffi_dl_processLibrary, 0) \
|
||||||
|
V(Ffi_dl_executableLibrary, 0) \
|
||||||
V(TransferableTypedData_factory, 2) \
|
V(TransferableTypedData_factory, 2) \
|
||||||
V(TransferableTypedData_materialize, 1)
|
V(TransferableTypedData_materialize, 1)
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,20 @@ part of dart.ffi;
|
||||||
|
|
||||||
/// Represents a dynamically loaded C library.
|
/// Represents a dynamically loaded C library.
|
||||||
class DynamicLibrary {
|
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.
|
/// 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);
|
external factory DynamicLibrary.open(String name);
|
||||||
|
|
||||||
/// Looks up a symbol in the [DynamicLibrary] and returns its address in
|
/// Looks up a symbol in the [DynamicLibrary] and returns its address in
|
||||||
|
|
|
@ -8,12 +8,13 @@
|
||||||
|
|
||||||
library FfiTest;
|
library FfiTest;
|
||||||
|
|
||||||
|
import 'dart:io';
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
|
|
||||||
import 'dylib_utils.dart';
|
|
||||||
|
|
||||||
import 'package:expect/expect.dart';
|
import 'package:expect/expect.dart';
|
||||||
|
|
||||||
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testOpen();
|
testOpen();
|
||||||
testOpenError();
|
testOpenError();
|
||||||
|
@ -42,6 +43,20 @@ void testLookup() {
|
||||||
DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
|
DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
|
||||||
var timesFour = l.lookupFunction<NativeDoubleUnOp, DoubleUnOp>("timesFour");
|
var timesFour = l.lookupFunction<NativeDoubleUnOp, DoubleUnOp>("timesFour");
|
||||||
Expect.approxEquals(12.0, timesFour(3));
|
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() {
|
void testLookupError() {
|
||||||
|
|
Loading…
Reference in a new issue