4cdb3f2c3a
- When return type is not directly supported and just a Dart_Handle, automatically create persistent handles - Change `Dart_LoadLibrary` to `Dart_LookupLibrary` - switch from iostream to cstdio, I have no idea why, but it doesn't work for me in emulators and it's not a big difference. TEST=ci,manual Change-Id: I9b6539c7f16e81af9e8a9ab3995d6040bac64a1d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/429962 Reviewed-by: Tess Strickland <sstrickl@google.com> Commit-Queue: Ivan Inozemtsev <iinozemtsev@google.com>
233 lines
5.9 KiB
Dart
233 lines
5.9 KiB
Dart
// Copyright (c) 2025, 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 'package:kernel/ast.dart';
|
|
import 'package:path/path.dart' as path;
|
|
|
|
import 'collector.dart' show EntryPointShimCollector;
|
|
|
|
class EntryPointShimWriter {
|
|
final String _headerPath;
|
|
final Library? _library;
|
|
final EntryPointShimCollector _collector;
|
|
|
|
EntryPointShimWriter(this._headerPath, this._library, this._collector);
|
|
|
|
static final _guardRegExp = RegExp(r"[^A-Za-z0-9]");
|
|
|
|
String get _headerGuardFromPath =>
|
|
_headerPath.replaceAll(_guardRegExp, "_").toUpperCase();
|
|
|
|
static const exportDirectiveDefinitions = '''
|
|
|
|
#ifdef __cplusplus
|
|
#define PACKAGE_EXTERN_C extern "C"
|
|
#else
|
|
#define PACKAGE_EXTERN_C extern
|
|
#endif
|
|
|
|
#if defined(__CYGWIN__)
|
|
#error Tool chain and platform not supported.
|
|
#elif defined(_WIN32)
|
|
#define PACKAGE_EXPORT PACKAGE_EXTERN_C __declspec(dllexport)
|
|
#else
|
|
#if __GNUC__ >= 4
|
|
#define PACKAGE_EXPORT PACKAGE_EXTERN_C __attribute__((visibility("default"))) __attribute((used))
|
|
#else
|
|
#error Tool chain not supported.
|
|
#endif
|
|
#endif
|
|
''';
|
|
|
|
static const exportDirectiveRemovals = '''
|
|
|
|
#undef PACKAGE_EXPORT
|
|
#undef PACKAGE_EXTERN_C
|
|
''';
|
|
|
|
void write(StringBuffer declarations, StringBuffer definitions) {
|
|
// Output helpers used by shim methods.
|
|
declarations.writeln('''
|
|
#ifndef $_headerGuardFromPath
|
|
#define $_headerGuardFromPath
|
|
|
|
#include "include/dart_engine.h"
|
|
''');
|
|
declarations.writeln(exportDirectiveDefinitions);
|
|
definitions.write('''
|
|
#include "${path.basename(_headerPath)}"
|
|
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
|
|
Dart_Handle CheckError(Dart_Handle handle, std::string_view context = "") {
|
|
if (Dart_IsError(handle)) {
|
|
std::string context_str(context);
|
|
fprintf(stderr, "Error %s: %s\\n", context_str.c_str(), Dart_GetError(handle));
|
|
exit(1);
|
|
}
|
|
return handle;
|
|
}
|
|
|
|
int64_t IntFromHandle(Dart_Handle handle) {
|
|
CheckError(handle, "IntFromHandle received an error");
|
|
|
|
if (!Dart_IsInteger(handle)) {
|
|
fprintf(stderr, "IntFromHandle handle is not an int\\n");
|
|
exit(1);
|
|
}
|
|
|
|
int64_t result;
|
|
Dart_Handle to_int64_result = Dart_IntegerToInt64(handle, &result);
|
|
CheckError(to_int64_result, "Dart_IntegerToInt64");
|
|
return result;
|
|
}
|
|
|
|
double DoubleFromHandle(Dart_Handle handle) {
|
|
CheckError(handle, "DoubleFromHandle received an error");
|
|
|
|
if (!Dart_IsDouble(handle)) {
|
|
fprintf(stderr, "DoubleFromHandle handle is not a double\\n");
|
|
exit(1);
|
|
}
|
|
|
|
double result;
|
|
Dart_Handle to_double_result = Dart_DoubleValue(handle, &result);
|
|
CheckError(to_double_result, "Dart_DoubleValue");
|
|
return result;
|
|
}
|
|
|
|
class PackageState {
|
|
public:
|
|
static PackageState* instance() {
|
|
static PackageState* instance = new PackageState();
|
|
return instance;
|
|
}
|
|
|
|
Dart_Handle PackageLibrary() {
|
|
ValidateCurrentIsolate();
|
|
Dart_Handle result = package_library_;
|
|
if (package_library_ == nullptr) {
|
|
result = ''');
|
|
if (_library == null) {
|
|
definitions.write('Dart_RootLibrary()');
|
|
} else {
|
|
definitions.write(
|
|
'Dart_LookupLibrary(Dart_NewStringFromCString(kLibraryUri))',
|
|
);
|
|
}
|
|
definitions.writeln(''';
|
|
if (!Dart_IsError(result)) {
|
|
package_library_ = Dart_NewPersistentHandle(result);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
Dart_Handle TypeWithDefaults(std::string name) {
|
|
ValidateCurrentIsolate();
|
|
auto search = default_types_.find(name);
|
|
Dart_Handle result;
|
|
if (search == default_types_.end()) {
|
|
Dart_Handle lib = PackageLibrary();
|
|
result = Dart_GetClass(lib, Dart_NewStringFromCString(name.c_str()));
|
|
if (!Dart_IsError(result)) {
|
|
Dart_PersistentHandle handle = Dart_NewPersistentHandle(result);
|
|
default_types_.emplace(std::make_pair(name, handle));
|
|
}
|
|
} else {
|
|
result = search->second;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private:''');
|
|
if (_library != null) {
|
|
definitions.writeln('''
|
|
static constexpr char kLibraryUri[] = "${_library.importUri}";
|
|
|
|
''');
|
|
}
|
|
definitions.writeln('''
|
|
PackageState() : default_types_() {}
|
|
|
|
void ValidateCurrentIsolate() {
|
|
Dart_Isolate current = Dart_CurrentIsolate();
|
|
if (isolate_ != current) {
|
|
isolate_ = current;
|
|
if (package_library_ != nullptr) {
|
|
Dart_DeletePersistentHandle(package_library_);
|
|
package_library_ = nullptr;
|
|
}
|
|
for (const auto& [str, handle] : default_types_) {
|
|
Dart_DeletePersistentHandle(handle);
|
|
}
|
|
default_types_.clear();
|
|
}
|
|
}
|
|
|
|
// Ensure the helper methods defined above won't trigger unused
|
|
// function warnings.
|
|
template <typename T>
|
|
static inline void USE(T&&) {}
|
|
|
|
void UseHelperFunctions() {
|
|
USE(IntFromHandle);
|
|
USE(DoubleFromHandle);
|
|
}
|
|
|
|
Dart_Isolate isolate_ = nullptr;
|
|
Dart_PersistentHandle package_library_ = nullptr;
|
|
std::unordered_map<std::string, Dart_PersistentHandle> default_types_;
|
|
};
|
|
|
|
class DartScope {
|
|
public:
|
|
DartScope() { Dart_EnterScope(); }
|
|
virtual ~DartScope() { Dart_ExitScope(); }
|
|
|
|
private:
|
|
DartScope(const DartScope&) = delete;
|
|
void operator=(const DartScope&) = delete;
|
|
};
|
|
|
|
class IsolateScope {
|
|
public:
|
|
explicit IsolateScope(Dart_Isolate isolate) {
|
|
DartEngine_AcquireIsolate(isolate);
|
|
}
|
|
virtual ~IsolateScope() { DartEngine_ReleaseIsolate(); }
|
|
|
|
private:
|
|
IsolateScope(const IsolateScope&) = delete;
|
|
void operator=(const IsolateScope&) = delete;
|
|
};
|
|
|
|
} // namespace
|
|
''');
|
|
definitions.writeln(exportDirectiveDefinitions);
|
|
for (final e in _collector.entries) {
|
|
final r = e.key;
|
|
declarations.write('''
|
|
// ${r.node!}
|
|
''');
|
|
for (final shim in e.value) {
|
|
shim.write(declarations, definitions);
|
|
}
|
|
}
|
|
declarations.writeln(exportDirectiveRemovals);
|
|
definitions.writeln(exportDirectiveRemovals);
|
|
declarations.write('''
|
|
|
|
#endif // $_headerGuardFromPath
|
|
''');
|
|
}
|
|
}
|