Revert "[ffi] NativeCallable.listener example."

This reverts commit 5354df624a.

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 <dacoharkes@google.com>
> Commit-Queue: Liam Appelbe <liama@google.com>

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 <aam@google.com>
Reviewed-by: Liam Appelbe <liama@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
Auto-Submit: Liam Appelbe <liama@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
This commit is contained in:
Liam Appelbe 2023-09-22 05:15:18 +00:00 committed by Commit Queue
parent 5354df624a
commit 18d0afdce1
10 changed files with 0 additions and 308 deletions

View file

@ -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",

View file

@ -1,6 +0,0 @@
.dart_tool
.packages
pubspec.lock
lib/libfake_http.so
lib/libfake_http.dylib
lib/fake_http.dll

View file

@ -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" ]
}

View file

@ -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`.

View file

@ -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<Uri>? paths}) =>
DynamicLibrary.open((paths ?? [Uri()])
.map((path) => dylibPath(name, path))
.firstWhere((lib) => File(lib.toFilePath()).existsSync())
.path);

View file

@ -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 <atomic>
#include <chrono>
#include <cstring>
#include <thread>
#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
<html>
<body>
Hello world!
</body>
</html>
)";
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();
}

View file

@ -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<String> httpGet(String uri) async {
// Create the NativeCallable.listener.
final completer = Completer<String>();
void onResponse(Pointer<Utf8> responsePointer) {
completer.complete(responsePointer.toDartString());
calloc.free(responsePointer);
}
final callback = NativeCallable<HttpCallback>.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<Utf8> requestPointer) {
onRequest(requestPointer.toDartString());
calloc.free(requestPointer);
}
final callback = NativeCallable<HttpCallback>.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<Utf8>);
typedef HttpGetFunction = void Function(
Pointer<Utf8>, Pointer<NativeFunction<HttpCallback>>);
typedef HttpGetNativeFunction = Void Function(
Pointer<Utf8>, Pointer<NativeFunction<HttpCallback>>);
final nativeHttpGet =
dylib.lookupFunction<HttpGetNativeFunction, HttpGetFunction>('http_get');
typedef HttpServeFunction = void Function(
Pointer<NativeFunction<HttpCallback>>);
typedef HttpServeNativeFunction = Void Function(
Pointer<NativeFunction<HttpCallback>>);
final nativeHttpServe = dylib
.lookupFunction<HttpServeNativeFunction, HttpServeFunction>('http_serve');
Future<void> 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');
}

View file

@ -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

View file

@ -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<void> main() async {
test('httpGet', () async {
final response = await httpGet('http://example.com');
expect(response, contains('Hello world!'));
});
test('httpServe', () async {
final completer = Completer<String>();
httpServe((request) => completer.complete(request));
final request = await completer.future;
expect(request, contains('www.example.com'));
});
}

View file

@ -214,83 +214,6 @@ abstract final class NativeCallable<T extends Function> {
///
/// 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<String> httpGet(String uri) async {
/// // Create the NativeCallable.listener.
/// final completer = Completer<String>();
/// void onResponse(Pointer<Utf8> responsePointer) {
/// completer.complete(responsePointer.toDartString());
/// calloc.free(responsePointer);
/// }
/// final callback = NativeCallable<HttpCallback>.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<Utf8> requestPointer) {
/// onRequest(requestPointer.toDartString());
/// calloc.free(requestPointer);
/// }
/// final callback = NativeCallable<HttpCallback>.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<Utf8>);
///
/// typedef HttpGetFunction = void Function(
/// Pointer<Utf8>, Pointer<NativeFunction<HttpCallback>>);
/// typedef HttpGetNativeFunction = Void Function(
/// Pointer<Utf8>, Pointer<NativeFunction<HttpCallback>>);
/// final nativeHttpGet =
/// dylib.lookupFunction<HttpGetNativeFunction, HttpGetFunction>(
/// 'http_get');
///
/// typedef HttpServeFunction = void Function(
/// Pointer<NativeFunction<HttpCallback>>);
/// typedef HttpServeNativeFunction = Void Function(
/// Pointer<NativeFunction<HttpCallback>>);
/// final nativeHttpServe =
/// dylib.lookupFunction<HttpServeNativeFunction, HttpServeFunction>(
/// 'http_serve');
/// ```
factory NativeCallable.listener(
@DartRepresentationOf("T") Function callback) {
throw UnsupportedError("NativeCallable cannot be constructed dynamically.");