From 18d0afdce1c9d2d06ca8c8e93dce3b4e1202b0a5 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Fri, 22 Sep 2023 05:15:18 +0000 Subject: [PATCH] Revert "[ffi] NativeCallable.listener example." This reverts commit 5354df624af5957f70f28b238a626d2976ce4f95. Reason for revert: Broke debian-x64-main bot https://logs.chromium.org/logs/dart-internal/buildbucket/cr-buildbucket/8769282695204884177/+/u/build/stdout Original change's description: > [ffi] NativeCallable.listener example. > > Add an example to the NativeCallable.listener documentation. > > Bug: https://github.com/dart-lang/sdk/issues/53435 > Change-Id: I4b664b14ca1dbc474913a9e191e38ca6f290350f > Fixes: https://github.com/dart-lang/sdk/issues/53435 > CoreLibraryReviewExempt: The FFI package is VM-only > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/326580 > Reviewed-by: Daco Harkes > Commit-Queue: Liam Appelbe Bug: https://github.com/dart-lang/sdk/issues/53435 Change-Id: Id959500df51d0eaa9bd452d3d9d0a8b21191de1c No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/327420 Reviewed-by: Alexander Aprelev Reviewed-by: Liam Appelbe Commit-Queue: Alexander Aprelev Auto-Submit: Liam Appelbe Bot-Commit: Rubber Stamper --- BUILD.gn | 1 - samples/ffi/http/.gitignore | 6 -- samples/ffi/http/BUILD.gn | 9 --- samples/ffi/http/README.md | 12 ---- samples/ffi/http/lib/dylib_utils.dart | 21 ------ samples/ffi/http/lib/fake_http.cc | 48 ------------- samples/ffi/http/lib/http.dart | 97 --------------------------- samples/ffi/http/pubspec.yaml | 12 ---- samples/ffi/http/test/http_test.dart | 25 ------- sdk/lib/ffi/ffi.dart | 77 --------------------- 10 files changed, 308 deletions(-) delete mode 100644 samples/ffi/http/.gitignore delete mode 100644 samples/ffi/http/BUILD.gn delete mode 100644 samples/ffi/http/README.md delete mode 100644 samples/ffi/http/lib/dylib_utils.dart delete mode 100644 samples/ffi/http/lib/fake_http.cc delete mode 100644 samples/ffi/http/lib/http.dart delete mode 100644 samples/ffi/http/pubspec.yaml delete mode 100644 samples/ffi/http/test/http_test.dart diff --git a/BUILD.gn b/BUILD.gn index 60545cebcd3..d6647ee1a55 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -48,7 +48,6 @@ group("runtime") { "runtime/bin:process_test", "runtime/bin:run_vm_tests", "runtime/vm:kernel_platform_files($host_toolchain)", - "samples/ffi/http:fake_http", "utils/dartdev:dartdev", "utils/dds:dds", "utils/kernel-service:kernel-service", diff --git a/samples/ffi/http/.gitignore b/samples/ffi/http/.gitignore deleted file mode 100644 index a18c42e5cee..00000000000 --- a/samples/ffi/http/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -.dart_tool -.packages -pubspec.lock -lib/libfake_http.so -lib/libfake_http.dylib -lib/fake_http.dll diff --git a/samples/ffi/http/BUILD.gn b/samples/ffi/http/BUILD.gn deleted file mode 100644 index b8b98e6fb73..00000000000 --- a/samples/ffi/http/BUILD.gn +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2023, 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. - -shared_library("fake_http") { - sources = [ "lib/fake_http.cc" ] - include_dirs = [ "." ] - ldflags = [ "-rdynamic" ] -} diff --git a/samples/ffi/http/README.md b/samples/ffi/http/README.md deleted file mode 100644 index 023a324632e..00000000000 --- a/samples/ffi/http/README.md +++ /dev/null @@ -1,12 +0,0 @@ -This is an example that shows how to use `NativeCallable.listener` to interact -with a multi threaded native API. - -The native API is a fake HTTP library with some hard coded requests and -responses. To build the dynamic library, run this command: - -```bash -c++ -shared -fpic lib/fake_http.cc -lstdc++ -o lib/libfake_http.so -``` - -On Windows the output library should be `lib/fake_http.dll` and on Mac it should -be `lib/libfake_http.dylib`. diff --git a/samples/ffi/http/lib/dylib_utils.dart b/samples/ffi/http/lib/dylib_utils.dart deleted file mode 100644 index e3ba4abdb38..00000000000 --- a/samples/ffi/http/lib/dylib_utils.dart +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2023, 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'; -import 'dart:io' show File, Platform; - -Uri dylibPath(String name, Uri path) { - if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia) { - return path.resolve("lib$name.so"); - } - if (Platform.isMacOS) return path.resolve("lib$name.dylib"); - if (Platform.isWindows) return path.resolve("$name.dll"); - throw Exception("Platform not implemented"); -} - -DynamicLibrary dlopenPlatformSpecific(String name, {List? paths}) => - DynamicLibrary.open((paths ?? [Uri()]) - .map((path) => dylibPath(name, path)) - .firstWhere((lib) => File(lib.toFilePath()).existsSync()) - .path); diff --git a/samples/ffi/http/lib/fake_http.cc b/samples/ffi/http/lib/fake_http.cc deleted file mode 100644 index 21a29875bd5..00000000000 --- a/samples/ffi/http/lib/fake_http.cc +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2023, 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. - -#include -#include -#include -#include - -#if defined(_WIN32) -#define DART_EXPORT extern "C" __declspec(dllexport) -#else -#define DART_EXPORT \ - extern "C" __attribute__((visibility("default"))) __attribute((used)) -#endif - -constexpr char kExampleRequest[] = R"( -GET / HTTP/1.1 -Host: www.example.com -)"; - -constexpr char kExampleResponse[] = R"( -HTTP/1.1 200 OK -Content-Length: 54 -Content-Type: text/html; charset=UTF-8 - - - - Hello world! - - -)"; - -DART_EXPORT void http_get(const char* uri, void (*onResponse)(const char*)) { - std::thread([onResponse]() { - std::this_thread::sleep_for(std::chrono::seconds(3)); - onResponse(strdup(kExampleResponse)); - }).detach(); -} - -DART_EXPORT void http_serve(void (*onRequest)(const char*)) { - std::thread([onRequest]() { - while (true) { - std::this_thread::sleep_for(std::chrono::seconds(1)); - onRequest(strdup(kExampleRequest)); - } - }).detach(); -} diff --git a/samples/ffi/http/lib/http.dart b/samples/ffi/http/lib/http.dart deleted file mode 100644 index 1fde486f72c..00000000000 --- a/samples/ffi/http/lib/http.dart +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2023, 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:async'; -import 'dart:ffi'; -import 'dart:io'; - -import 'package:ffi/ffi.dart'; - -import 'dylib_utils.dart'; - -// Runs a simple HTTP GET request using a native HTTP library that runs -// the request on a background thread. -Future httpGet(String uri) async { - // Create the NativeCallable.listener. - final completer = Completer(); - void onResponse(Pointer responsePointer) { - completer.complete(responsePointer.toDartString()); - calloc.free(responsePointer); - } - - final callback = NativeCallable.listener(onResponse); - - // Invoke the native HTTP API. Our example HTTP library runs our GET - // request on a background thread, and calls the callback on that same - // thread when it receives the response. - final uriPointer = uri.toNativeUtf8(); - nativeHttpGet(uriPointer, callback.nativeFunction); - calloc.free(uriPointer); - - // Wait for the response. - final response = await completer.future; - - // Remember to close the NativeCallable once the native API is finished - // with it, otherwise this isolate will stay alive indefinitely. - callback.close(); - - return response; -} - -// Start a HTTP server on a background thread. -void httpServe(void Function(String) onRequest) { - // Create the NativeCallable.listener. - void onNativeRequest(Pointer requestPointer) { - onRequest(requestPointer.toDartString()); - calloc.free(requestPointer); - } - - final callback = NativeCallable.listener(onNativeRequest); - - // Invoke the native function to start the HTTP server. Our example - // HTTP library will start a server on a background thread, and pass - // any requests it receives to out callback. - nativeHttpServe(callback.nativeFunction); - - // The server will run indefinitely, and the callback needs to stay - // alive for that whole time, so we can't close the callback here. - // But we also don't want the callback to keep the isolate alive - // forever, so we set keepIsolateAlive to false. - callback.keepIsolateAlive = false; -} - -// Load the native functions from a DynamicLibrary. -late final DynamicLibrary dylib = dlopenPlatformSpecific('fake_http', paths: [ - Platform.script.resolve('../lib/'), - Uri.file(Platform.resolvedExecutable), -]); -typedef HttpCallback = Void Function(Pointer); - -typedef HttpGetFunction = void Function( - Pointer, Pointer>); -typedef HttpGetNativeFunction = Void Function( - Pointer, Pointer>); -final nativeHttpGet = - dylib.lookupFunction('http_get'); - -typedef HttpServeFunction = void Function( - Pointer>); -typedef HttpServeNativeFunction = Void Function( - Pointer>); -final nativeHttpServe = dylib - .lookupFunction('http_serve'); - -Future main() async { - print('Sending GET request...'); - final response = await httpGet('http://example.com'); - print('Received a response: $response'); - - print('Starting HTTP server...'); - httpServe((String request) { - print('Received a request: $request'); - }); - - await Future.delayed(Duration(seconds: 10)); - print('All done'); -} diff --git a/samples/ffi/http/pubspec.yaml b/samples/ffi/http/pubspec.yaml deleted file mode 100644 index 2798023736c..00000000000 --- a/samples/ffi/http/pubspec.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: http -version: 0.0.1 -publish_to: none - -environment: - sdk: '>=3.0.0 <4.0.0' - -dependencies: - ffi: ^2.1.0 - -dev_dependencies: - test: ^1.21.1 diff --git a/samples/ffi/http/test/http_test.dart b/samples/ffi/http/test/http_test.dart deleted file mode 100644 index 509d8dd76c7..00000000000 --- a/samples/ffi/http/test/http_test.dart +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2023, 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:async'; -import 'dart:io'; - -import 'package:ffi/ffi.dart'; -import 'package:test/test.dart'; - -import '../lib/http.dart'; - -Future main() async { - test('httpGet', () async { - final response = await httpGet('http://example.com'); - expect(response, contains('Hello world!')); - }); - - test('httpServe', () async { - final completer = Completer(); - httpServe((request) => completer.complete(request)); - final request = await completer.future; - expect(request, contains('www.example.com')); - }); -} diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart index a24c7a0f9ea..45e014c1d4e 100644 --- a/sdk/lib/ffi/ffi.dart +++ b/sdk/lib/ffi/ffi.dart @@ -214,83 +214,6 @@ abstract final class NativeCallable { /// /// This callback must be [close]d when it is no longer needed. The [Isolate] /// that created the callback will be kept alive until [close] is called. - /// - /// For example: - /// - /// ```dart - /// import 'dart:async'; - /// import 'dart:ffi'; - /// import 'package:ffi/ffi.dart'; - /// - /// // Runs a simple HTTP GET request using a native HTTP library that runs - /// // the request on a background thread. - /// Future httpGet(String uri) async { - /// // Create the NativeCallable.listener. - /// final completer = Completer(); - /// void onResponse(Pointer responsePointer) { - /// completer.complete(responsePointer.toDartString()); - /// calloc.free(responsePointer); - /// } - /// final callback = NativeCallable.listener(onResponse); - /// - /// // Invoke the native HTTP API. Our example HTTP library runs our GET - /// // request on a background thread, and calls the callback on that same - /// // thread when it receives the response. - /// final uriPointer = uri.toNativeUtf8(); - /// nativeHttpGet(uriPointer, callback.nativeFunction); - /// calloc.free(uriPointer); - /// - /// // Wait for the response. - /// final response = await completer.future; - /// - /// // Remember to close the NativeCallable once the native API is finished - /// // with it, otherwise this isolate will stay alive indefinitely. - /// callback.close(); - /// - /// return response; - /// } - /// - /// // Start a HTTP server on a background thread. - /// void httpServe(void Function(String) onRequest) { - /// // Create the NativeCallable.listener. - /// void onNativeRequest(Pointer requestPointer) { - /// onRequest(requestPointer.toDartString()); - /// calloc.free(requestPointer); - /// } - /// final callback = NativeCallable.listener(onNativeRequest); - /// - /// // Invoke the native function to start the HTTP server. Our example - /// // HTTP library will start a server on a background thread, and pass - /// // any requests it receives to out callback. - /// nativeHttpServe(callback.nativeFunction); - /// - /// // The server will run indefinitely, and the callback needs to stay - /// // alive for that whole time, so we can't close the callback here. - /// // But we also don't want the callback to keep the isolate alive - /// // forever, so we set keepIsolateAlive to false. - /// callback.keepIsolateAlive = false; - /// } - /// - /// // Load the native functions from a DynamicLibrary. - /// late final DynamicLibrary dylib = DynamicLibrary.process(); - /// typedef HttpCallback = Void Function(Pointer); - /// - /// typedef HttpGetFunction = void Function( - /// Pointer, Pointer>); - /// typedef HttpGetNativeFunction = Void Function( - /// Pointer, Pointer>); - /// final nativeHttpGet = - /// dylib.lookupFunction( - /// 'http_get'); - /// - /// typedef HttpServeFunction = void Function( - /// Pointer>); - /// typedef HttpServeNativeFunction = Void Function( - /// Pointer>); - /// final nativeHttpServe = - /// dylib.lookupFunction( - /// 'http_serve'); - /// ``` factory NativeCallable.listener( @DartRepresentationOf("T") Function callback) { throw UnsupportedError("NativeCallable cannot be constructed dynamically.");