Skip to content

Commit f7192b6

Browse files
dcharkescommit-bot@chromium.org
authored andcommitted
[vm/ffi] Expose dart_native_api.h symbols via dart:ffi
This enables dynamic linking of the symbols in dart_native_api.h to work around the Windows linking issue and Dart embedders not exposing symbols. Issue: #40607 Closes: #40564 Change-Id: I6f797cc915b53ec63fa5953529f17c40e52a2aed Cq-Include-Trybots: luci.dart.try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-dartkb-linux-release-x64-abi-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136962 Commit-Queue: Daco Harkes <[email protected]> Reviewed-by: Vyacheslav Egorov <[email protected]> Reviewed-by: Martin Kustermann <[email protected]>
1 parent 94c031c commit f7192b6

File tree

10 files changed

+220
-14
lines changed

10 files changed

+220
-14
lines changed

runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,34 @@ DART_EXPORT intptr_t TestCallbackWrongIsolate(void (*fn)()) {
269269

270270
#endif // defined(TARGET_OS_LINUX)
271271

272+
////////////////////////////////////////////////////////////////////////////////
273+
// Dynamic linking of dart_native_api.h for the next two samples.
274+
typedef bool (*Dart_PostCObjectType)(Dart_Port port_id, Dart_CObject* message);
275+
Dart_PostCObjectType Dart_PostCObject_ = nullptr;
276+
277+
DART_EXPORT void RegisterDart_PostCObject(
278+
Dart_PostCObjectType function_pointer) {
279+
Dart_PostCObject_ = function_pointer;
280+
}
281+
282+
typedef Dart_Port (*Dart_NewNativePortType)(const char* name,
283+
Dart_NativeMessageHandler handler,
284+
bool handle_concurrently);
285+
Dart_NewNativePortType Dart_NewNativePort_ = nullptr;
286+
287+
DART_EXPORT void RegisterDart_NewNativePort(
288+
Dart_NewNativePortType function_pointer) {
289+
Dart_NewNativePort_ = function_pointer;
290+
}
291+
292+
typedef bool (*Dart_CloseNativePortType)(Dart_Port native_port_id);
293+
Dart_CloseNativePortType Dart_CloseNativePort_ = nullptr;
294+
295+
DART_EXPORT void RegisterDart_CloseNativePort(
296+
Dart_CloseNativePortType function_pointer) {
297+
Dart_CloseNativePort_ = function_pointer;
298+
}
299+
272300
////////////////////////////////////////////////////////////////////////////////
273301
// Functions for async callbacks example.
274302
//
@@ -314,7 +342,7 @@ void NotifyDart(Dart_Port send_port, const Work* work) {
314342
dart_object.type = Dart_CObject_kInt64;
315343
dart_object.value.as_int64 = work_addr;
316344

317-
const bool result = Dart_PostCObject(send_port, &dart_object);
345+
const bool result = Dart_PostCObject_(send_port, &dart_object);
318346
if (!result) {
319347
FATAL("C : Posting message to port failed.");
320348
}
@@ -476,16 +504,16 @@ class PendingCall {
476504
PendingCall(void** buffer, size_t* length)
477505
: response_buffer_(buffer), response_length_(length) {
478506
receive_port_ =
479-
Dart_NewNativePort("cpp-response", &PendingCall::HandleResponse,
480-
/*handle_concurrently=*/false);
507+
Dart_NewNativePort_("cpp-response", &PendingCall::HandleResponse,
508+
/*handle_concurrently=*/false);
481509
}
482-
~PendingCall() { Dart_CloseNativePort(receive_port_); }
510+
~PendingCall() { Dart_CloseNativePort_(receive_port_); }
483511

484512
Dart_Port port() const { return receive_port_; }
485513

486514
void PostAndWait(Dart_Port port, Dart_CObject* object) {
487515
std::unique_lock<std::mutex> lock(mutex);
488-
const bool success = Dart_PostCObject(send_port_, object);
516+
const bool success = Dart_PostCObject_(send_port_, object);
489517
if (!success) FATAL("Failed to send message, invalid port or isolate died");
490518

491519
printf("C : Waiting for result.\n");
@@ -589,7 +617,7 @@ uint8_t MyCallback1(uint8_t a) {
589617
c_request.value.as_array.length =
590618
sizeof(c_request_arr) / sizeof(c_request_arr[0]);
591619

592-
printf("C : Dart_PostCObject(request: %" Px ", call: %" Px ").\n",
620+
printf("C : Dart_PostCObject_(request: %" Px ", call: %" Px ").\n",
593621
reinterpret_cast<intptr_t>(&c_request),
594622
reinterpret_cast<intptr_t>(&c_pending_call));
595623
pending_call.PostAndWait(send_port_, &c_request);
@@ -637,10 +665,10 @@ void MyCallback2(uint8_t a) {
637665
c_request.value.as_array.length =
638666
sizeof(c_request_arr) / sizeof(c_request_arr[0]);
639667

640-
printf("C : Dart_PostCObject(request: %" Px ", call: %" Px ").\n",
668+
printf("C : Dart_PostCObject_(request: %" Px ", call: %" Px ").\n",
641669
reinterpret_cast<intptr_t>(&c_request),
642670
reinterpret_cast<intptr_t>(&c_pending_call));
643-
Dart_PostCObject(send_port_, &c_request);
671+
Dart_PostCObject_(send_port_, &c_request);
644672
}
645673

646674
// Simulated work for Thread #1.

runtime/lib/ffi.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
#include "include/dart_api.h"
6+
#include "include/dart_native_api.h"
67
#include "platform/globals.h"
78
#include "vm/bootstrap_natives.h"
89
#include "vm/class_finalizer.h"
@@ -492,4 +493,21 @@ DEFINE_NATIVE_ENTRY(Ffi_pointerFromFunction, 1, 1) {
492493
return Pointer::New(type_arg, entry_point);
493494
}
494495

496+
DEFINE_NATIVE_ENTRY(NativeApiFunctionPointer, 0, 1) {
497+
GET_NON_NULL_NATIVE_ARGUMENT(String, name_dart, arguments->NativeArgAt(0));
498+
const char* name = name_dart.ToCString();
499+
500+
if (strcmp(name, "Dart_PostCObject") == 0) {
501+
return Integer::New(reinterpret_cast<int64_t>(Dart_PostCObject));
502+
} else if (strcmp(name, "Dart_NewNativePort") == 0) {
503+
return Integer::New(reinterpret_cast<int64_t>(Dart_NewNativePort));
504+
} else if (strcmp(name, "Dart_CloseNativePort") == 0) {
505+
return Integer::New(reinterpret_cast<int64_t>(Dart_CloseNativePort));
506+
}
507+
508+
const String& error = String::Handle(
509+
String::NewFormatted("Unknown dart_native_api.h symbol: %s.", name));
510+
Exceptions::ThrowArgumentError(error);
511+
}
512+
495513
} // namespace dart

runtime/vm/bootstrap_natives.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ namespace dart {
406406
V(Ffi_asExternalTypedData, 2) \
407407
V(Ffi_dl_processLibrary, 0) \
408408
V(Ffi_dl_executableLibrary, 0) \
409+
V(NativeApiFunctionPointer, 1) \
409410
V(TransferableTypedData_factory, 2) \
410411
V(TransferableTypedData_materialize, 1) \
411412
V(Wasm_initModule, 2) \

samples/ffi/async/sample_async_callback.dart

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
// main Dart thread.
88
//
99
// TODO(dartbug.com/37022): Update this when we get real async callbacks.
10-
// TODO(dartbug.com/40564): On Windows DLL is wrongly linked against dart.exe
11-
// instead of dart_precompiled_runtime.exe
1210

1311
import 'dart:ffi';
1412
import 'dart:isolate';
@@ -28,8 +26,9 @@ main() async {
2826
print("C T2 = Some C thread executing C.");
2927
print("C = C T1 or C T2.");
3028
print("Dart: Setup.");
31-
final interactiveCppRequests = ReceivePort()..listen(requestExecuteCallback);
29+
registerDart_PostCObject(NativeApi.nativeApiPostCObject);
3230

31+
final interactiveCppRequests = ReceivePort()..listen(requestExecuteCallback);
3332
final int nativePort = interactiveCppRequests.sendPort.nativePort;
3433
registerCallback1(nativePort, callback1FP);
3534
registerCallback2(nativePort, callback2FP);
@@ -102,6 +101,14 @@ final stopWorkSimulator =
102101
final executeCallback = dl.lookupFunction<Void Function(Pointer<Work>),
103102
void Function(Pointer<Work>)>('ExecuteCallback');
104103

104+
final registerDart_PostCObject = dl.lookupFunction<
105+
Void Function(
106+
Pointer<NativeFunction<Int8 Function(Int64, Pointer<Dart_CObject>)>>
107+
functionPointer),
108+
void Function(
109+
Pointer<NativeFunction<Int8 Function(Int64, Pointer<Dart_CObject>)>>
110+
functionPointer)>('RegisterDart_PostCObject');
111+
105112
class Work extends Struct {}
106113

107114
Future asyncSleep(int ms) {

samples/ffi/async/sample_native_port_call.dart

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ main() async {
3535
print("C T2 = Some C thread executing C.");
3636
print("C = C T1 or C T2.");
3737
print("Dart: Setup.");
38+
registerDart_PostCObject(NativeApi.nativeApiPostCObject);
39+
registerDart_NewNativePort(NativeApi.nativeApiNewNativePort);
40+
registerDart_CloseNativePort(NativeApi.nativeApiCloseNativePort);
41+
3842
final interactiveCppRequests = ReceivePort()..listen(handleCppRequests);
3943
final int nativePort = interactiveCppRequests.sendPort.nativePort;
4044
registerSendPort(nativePort);
@@ -126,6 +130,39 @@ final startWorkSimulator2 =
126130
final stopWorkSimulator2 =
127131
dl.lookupFunction<Void Function(), void Function()>('StopWorkSimulator2');
128132

133+
final registerDart_PostCObject = dl.lookupFunction<
134+
Void Function(
135+
Pointer<NativeFunction<Int8 Function(Int64, Pointer<Dart_CObject>)>>
136+
functionPointer),
137+
void Function(
138+
Pointer<NativeFunction<Int8 Function(Int64, Pointer<Dart_CObject>)>>
139+
functionPointer)>('RegisterDart_PostCObject');
140+
141+
final registerDart_NewNativePort = dl.lookupFunction<
142+
Void Function(
143+
Pointer<
144+
NativeFunction<
145+
Int64 Function(
146+
Pointer<Uint8>,
147+
Pointer<NativeFunction<Dart_NativeMessageHandler>>,
148+
Int8)>>
149+
functionPointer),
150+
void Function(
151+
Pointer<
152+
NativeFunction<
153+
Int64 Function(
154+
Pointer<Uint8>,
155+
Pointer<NativeFunction<Dart_NativeMessageHandler>>,
156+
Int8)>>
157+
functionPointer)>('RegisterDart_NewNativePort');
158+
159+
final registerDart_CloseNativePort = dl.lookupFunction<
160+
Void Function(
161+
Pointer<NativeFunction<Int8 Function(Int64)>> functionPointer),
162+
void Function(
163+
Pointer<NativeFunction<Int8 Function(Int64)>> functionPointer)>(
164+
'RegisterDart_CloseNativePort');
165+
129166
Future asyncSleep(int ms) {
130167
return new Future.delayed(Duration(milliseconds: ms), () => true);
131168
}

samples/samples.status

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ sample_extension/test/sample_extension_app_snapshot_test: SkipByDesign # This te
1414
[ $compiler == dart2js && $runtime == none ]
1515
*: Fail, Pass # TODO(ahe): Triage these tests.
1616

17-
[ $compiler == dartkp && $system == windows ]
18-
ffi/async/async_test: Skip # dartbug.com/40564 dartbug.com/40579
19-
2017
[ $compiler == none && $mode == debug && $runtime == vm && $system == windows ]
2118
sample_extension/test/sample_extension_app_snapshot_test: Pass, RuntimeError # Issue 28842
2219

sdk/lib/_internal/vm/lib/ffi_patch.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,3 +452,27 @@ extension NativePort on SendPort {
452452
@patch
453453
int get nativePort native "SendPortImpl_get_id";
454454
}
455+
456+
int _nativeApiFunctionPointer(String symbol) native "NativeApiFunctionPointer";
457+
458+
@patch
459+
class NativeApi {
460+
@patch
461+
static Pointer<NativeFunction<Int8 Function(Int64, Pointer<Dart_CObject>)>>
462+
get nativeApiPostCObject =>
463+
Pointer.fromAddress(_nativeApiFunctionPointer("Dart_PostCObject"));
464+
465+
@patch
466+
static Pointer<
467+
NativeFunction<
468+
Int64 Function(
469+
Pointer<Uint8>,
470+
Pointer<NativeFunction<Dart_NativeMessageHandler>>,
471+
Int8)>> get nativeApiNewNativePort =>
472+
Pointer.fromAddress(_nativeApiFunctionPointer("Dart_NewNativePort"));
473+
474+
@patch
475+
static Pointer<NativeFunction<Int8 Function(Int64)>>
476+
get nativeApiCloseNativePort => Pointer.fromAddress(
477+
_nativeApiFunctionPointer("Dart_CloseNativePort"));
478+
}

sdk/lib/ffi/ffi.dart

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,3 +622,38 @@ extension NativePort on SendPort {
622622
/// `dart_native_api.h`.
623623
external int get nativePort;
624624
}
625+
626+
/// Opaque, not exposing it's members.
627+
class Dart_CObject extends Struct {}
628+
629+
typedef Dart_NativeMessageHandler = Void Function(Int64, Pointer<Dart_CObject>);
630+
631+
/// Exposes function pointers to functions in `dart_native_api.h`.
632+
class NativeApi {
633+
/// A function pointer to
634+
/// `bool Dart_PostCObject(Dart_Port port_id, Dart_CObject* message)`
635+
/// in `dart_native_api.h`.
636+
external static Pointer<
637+
NativeFunction<Int8 Function(Int64, Pointer<Dart_CObject>)>>
638+
get nativeApiPostCObject;
639+
640+
/// A function pointer to
641+
/// ```
642+
/// Dart_Port Dart_NewNativePort(const char* name,
643+
/// Dart_NativeMessageHandler handler,
644+
/// bool handle_concurrently)
645+
/// ```
646+
/// in `dart_native_api.h`.
647+
external static Pointer<
648+
NativeFunction<
649+
Int64 Function(
650+
Pointer<Uint8>,
651+
Pointer<NativeFunction<Dart_NativeMessageHandler>>,
652+
Int8)>> get nativeApiNewNativePort;
653+
654+
/// A function pointer to
655+
/// `bool Dart_CloseNativePort(Dart_Port native_port_id)`
656+
/// in `dart_native_api.h`.
657+
external static Pointer<NativeFunction<Int8 Function(Int64)>>
658+
get nativeApiCloseNativePort;
659+
}

sdk_nnbd/lib/_internal/vm/lib/ffi_patch.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,3 +450,27 @@ extension NativePort on SendPort {
450450
@patch
451451
int get nativePort native "SendPortImpl_get_id";
452452
}
453+
454+
int _nativeApiFunctionPointer(String symbol) native "NativeApiFunctionPointer";
455+
456+
@patch
457+
class NativeApi {
458+
@patch
459+
static Pointer<NativeFunction<Int8 Function(Int64, Pointer<Dart_CObject>)>>
460+
get nativeApiPostCObject =>
461+
Pointer.fromAddress(_nativeApiFunctionPointer("Dart_PostCObject"));
462+
463+
@patch
464+
static Pointer<
465+
NativeFunction<
466+
Int64 Function(
467+
Pointer<Uint8>,
468+
Pointer<NativeFunction<Dart_NativeMessageHandler>>,
469+
Int8)>> get nativeApiNewNativePort =>
470+
Pointer.fromAddress(_nativeApiFunctionPointer("Dart_NewNativePort"));
471+
472+
@patch
473+
static Pointer<NativeFunction<Int8 Function(Int64)>>
474+
get nativeApiCloseNativePort => Pointer.fromAddress(
475+
_nativeApiFunctionPointer("Dart_CloseNativePort"));
476+
}

sdk_nnbd/lib/ffi/ffi.dart

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,3 +621,38 @@ extension NativePort on SendPort {
621621
/// `dart_native_api.h`.
622622
external int get nativePort;
623623
}
624+
625+
/// Opaque, not exposing it's members.
626+
class Dart_CObject extends Struct {}
627+
628+
typedef Dart_NativeMessageHandler = Void Function(Int64, Pointer<Dart_CObject>);
629+
630+
/// Exposes function pointers to functions in `dart_native_api.h`.
631+
class NativeApi {
632+
/// A function pointer to
633+
/// `bool Dart_PostCObject(Dart_Port port_id, Dart_CObject* message)`
634+
/// in `dart_native_api.h`.
635+
external static Pointer<
636+
NativeFunction<Int8 Function(Int64, Pointer<Dart_CObject>)>>
637+
get nativeApiPostCObject;
638+
639+
/// A function pointer to
640+
/// ```
641+
/// Dart_Port Dart_NewNativePort(const char* name,
642+
/// Dart_NativeMessageHandler handler,
643+
/// bool handle_concurrently)
644+
/// ```
645+
/// in `dart_native_api.h`.
646+
external static Pointer<
647+
NativeFunction<
648+
Int64 Function(
649+
Pointer<Uint8>,
650+
Pointer<NativeFunction<Dart_NativeMessageHandler>>,
651+
Int8)>> get nativeApiNewNativePort;
652+
653+
/// A function pointer to
654+
/// `bool Dart_CloseNativePort(Dart_Port native_port_id)`
655+
/// in `dart_native_api.h`.
656+
external static Pointer<NativeFunction<Int8 Function(Int64)>>
657+
get nativeApiCloseNativePort;
658+
}

0 commit comments

Comments
 (0)