Dart:如何在本机扩展中创建流

2024-05-13

在我的本机扩展中,我需要将整数流式传输到我的 Dart 控制台应用程序。在概念上非常相似 标准输入。如何创建向控制台应用程序公开的本机 Dart Stream 对象?


我尝试为您创建一个示例并将其放在 github 上。

https://github.com/mezoni/native_extension_with_stream https://github.com/mezoni/native_extension_with_stream

如果您希望看到它的实际效果,您应该编译并运行它。

构建脚本位于bin/makefile.dart.

示例脚本位于bin/example_use_sample_extension.dart.

如果您只想查看源代码示例,可以在下面查看。

example_use_sample_extension.dart

import "package:lists/lists.dart";
import "package:native_extension_with_stream/sample_extension.dart";

void main() {
  print("Range from 0 to 5");
  var stream = NativeStream.createStream(new RangeList(0, 5));
  stream.listen((data) {
    print(data);
  }, onDone: () {
    print("Collection from -5 to 5 with step 2");
    var stream = NativeStream.createStream(new StepList(-5, 5, 2));
    stream.listen((data) {
      print(data);
    });
  });
}

样本扩展.dart

library native_extension_with_stream.sample_extension;

import "dart-ext:sample_extension";
import "dart:async";

class NativeStream {
  static Stream<int> createStream(Iterable<int> collection) {
    if (collection == null) {
      throw new ArgumentError("collection: $collection");
    }

    return _createStream(collection);
  }

  static Stream<int> _createStream(Iterable<int> collection) native
      "CreateStream";
}

样本扩展.cc

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#ifdef _WIN32
#include "windows.h"
#else
#include <stdbool.h>
#include <dlfcn.h>
#include <unistd.h>
#include <sys/mman.h>
#endif

#include "dart_api.h"

Dart_NativeFunction ResolveName(Dart_Handle name, int argc, bool* auto_setup_scope);

DART_EXPORT Dart_Handle sample_extension_Init(Dart_Handle parent_library) {  
  if (Dart_IsError(parent_library)) { return parent_library; }

  Dart_Handle result_code = Dart_SetNativeResolver(parent_library, ResolveName, NULL);
  if (Dart_IsError(result_code)) return result_code;

  return Dart_Null();
}

Dart_Handle HandleError(Dart_Handle handle) {
  if (Dart_IsError(handle)) Dart_PropagateError(handle);
  return handle;
}

void CreateStream(Dart_NativeArguments arguments) {
  Dart_Handle collection; 
  Dart_Handle library_async;
  Dart_Handle library_core;  
  Dart_Handle result;  
  Dart_Handle stream;  
  Dart_Handle type_int;
  Dart_Handle type_stream;
  Dart_Handle url_async;
  Dart_Handle url_core;

  Dart_EnterScope();
  collection = Dart_GetNativeArgument(arguments, 0);      
  url_async = Dart_NewStringFromCString("dart:async");
  url_core = Dart_NewStringFromCString("dart:core");  
  library_async = Dart_LookupLibrary(url_async);
  library_core = Dart_LookupLibrary(url_core);      
  type_int = Dart_GetType(library_core, Dart_NewStringFromCString("int"), 0, NULL);  
  type_stream = Dart_GetType(library_core, Dart_NewStringFromCString("Stream"), 0, NULL);
  stream = Dart_New(type_stream, Dart_NewStringFromCString("fromIterable"), 1, &collection);    
  Dart_SetReturnValue(arguments, stream);
  Dart_ExitScope();
}

struct FunctionLookup {
  const char* name;
  Dart_NativeFunction function;
};

FunctionLookup function_list[] = {
  {"CreateStream", CreateStream},  
  {NULL, NULL}};

Dart_NativeFunction ResolveName(Dart_Handle name, int argc, bool* auto_setup_scope) {
  if (!Dart_IsString(name)) return NULL;
  Dart_NativeFunction result = NULL;
  Dart_EnterScope();
  const char* cname;
  HandleError(Dart_StringToCString(name, &cname));

  for (int i=0; function_list[i].name != NULL; ++i) {
    if (strcmp(function_list[i].name, cname) == 0) {
      result = function_list[i].function;
      break;
    }
  }
  Dart_ExitScope();
  return result;
}

P.S.

这是构建脚本的源代码:

生成文件.dart

import "dart:io";
import "package:ccompilers/ccompilers.dart";
import "package:build_tools/build_shell.dart";
import "package:build_tools/build_tools.dart";
import "package:file_utils/file_utils.dart";
import "package:patsubst/top_level.dart";

void main(List<String> args) {
  const String PROJECT_NAME = "sample_extension";
  const String LIBNAME_LINUX = "lib$PROJECT_NAME.so";
  const String LIBNAME_MACOS = "lib$PROJECT_NAME.dylib";
  const String LIBNAME_WINDOWS = "$PROJECT_NAME.dll";

  // Determine operating system
  var os = Platform.operatingSystem;

  // Setup Dart SDK bitness for extension
  var bits = DartSDK.getVmBits();

  // Compiler options
  var compilerDefine = {};
  var compilerInclude = ['$DART_SDK/bin', '$DART_SDK/include'];

  // Linker options
  var linkerLibpath = <String>[];

  // OS dependent parameters
  var libname = "";
  var objExtension = "";
  switch (os) {
    case "linux":
      libname = LIBNAME_LINUX;
      objExtension = ".o";
      break;
    case "macos":
      libname = LIBNAME_MACOS;
      objExtension = ".o";
      break;
    case "windows":
      libname = LIBNAME_WINDOWS;
      objExtension = ".obj";
      break;
    default:
      print("Unsupported operating system: $os");
      exit(-1);
  }

  // http://dartbug.com/20119
  var bug20119 = Platform.script;

  // Set working directory
  FileUtils.chdir("../lib/src");

  // C++ files
  var cppFiles = FileUtils.glob("*.cc");
  if (os != "windows") {
    cppFiles = FileUtils.exclude(cppFiles, "sample_extension_dllmain_win.cc");
  }

  cppFiles = cppFiles.map((e) => FileUtils.basename(e));

  // Object files
  var objFiles = patsubst("%.cc", "%${objExtension}").replaceAll(cppFiles);

  // Makefile
  // Target: default
  target("default", ["build"], null, description: "Build and clean.");

  // Target: build
  target("build", ["clean_all", "compile_link", "clean"], (Target t, Map args) {
    print("The ${t.name} successful.");
  }, description: "Build '$PROJECT_NAME'.");

  // Target: compile_link
  target("compile_link", [libname], (Target t, Map args) {
    print("The ${t.name} successful.");
  }, description: "Compile and link '$PROJECT_NAME'.");

  // Target: clean
  target("clean", [], (Target t, Map args) {
    FileUtils.rm(["*.exp", "*.lib", "*.o", "*.obj"], force: true);
    print("The ${t.name} successful.");
  }, description: "Deletes all intermediate files.", reusable: true);

  // Target: clean_all
  target("clean_all", ["clean"], (Target t, Map args) {
    FileUtils.rm([libname], force: true);
    print("The ${t.name} successful.");
  }, description: "Deletes all intermediate and output files.", reusable: true);

  // Compile on Posix
  rule("%.o", ["%.cc"], (Target t, Map args) {
    var args = new CommandLineArguments();
    var compiler = new Gpp();
    args.add('-c');
    args.addAll(['-fPIC', '-Wall']);
    args.add('-m32', test: bits == 32);
    args.add('-m64', test: bits == 64);
    args.addAll(compilerInclude, prefix: '-I');
    args.addKeys(compilerDefine, prefix: '-D');
    args.addAll(t.sources);
    return compiler.run(args.arguments).exitCode;
  });

  // Compile on Windows
  rule("%.obj", ["%.cc"], (Target t, Map args) {
    var args = new CommandLineArguments();
    var compiler = new Msvc(bits: bits);
    args.add('/c');
    args.addAll(t.sources);
    args.addAll(compilerInclude, prefix: '-I');
    args.addKeys(compilerDefine, prefix: '-D');
    args.addKey('DART_SHARED_LIB', null, prefix: '-D');
    return compiler.run(args.arguments).exitCode;
  });

  // Link on Linux
  file(LIBNAME_LINUX, objFiles, (Target t, Map args) {
    var args = new CommandLineArguments();
    var linker = new Gcc();
    args.addAll(t.sources);
    args.add('-m32', test: bits == 32);
    args.add('-m64', test: bits == 64);
    args.addAll(linkerLibpath, prefix: '-L');
    args.add('-shared');
    args.addAll(['-o', t.name]);
    return linker.run(args.arguments).exitCode;
  });

  // Link on Macos
  file(LIBNAME_MACOS, objFiles, (Target t, Map args) {
    var args = new CommandLineArguments();
    var linker = new Gcc();
    args.addAll(t.sources);
    args.add('-m32', test: bits == 32);
    args.add('-m64', test: bits == 64);
    args.addAll(linkerLibpath, prefix: '-L');
    args.addAll(['-dynamiclib', '-undefined', 'dynamic_lookup']);
    args.addAll(['-o', t.name]);
    return linker.run(args.arguments).exitCode;
  });

  // Link on Windows
  file(LIBNAME_WINDOWS, objFiles, (Target t, Map args) {
    var args = new CommandLineArguments();
    var linker = new Mslink(bits: bits);
    args.add('/DLL');
    args.addAll(t.sources);
    args.addAll(['dart.lib']);
    args.addAll(linkerLibpath, prefix: '/LIBPATH:');
    args.add('$DART_SDK/bin', prefix: '/LIBPATH:');
    args.add(t.name, prefix: '/OUT:');
    return linker.run(args.arguments).exitCode;
  });

  new BuildShell().run(args).then((exitCode) => exit(exitCode));
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Dart:如何在本机扩展中创建流 的相关文章

随机推荐

  • 多种邮件配置

    我使用 mandrill 驱动程序配置了 laravel 的邮件服务 这里没有问题 现在 在我申请的某个时刻 我需要通过 gmail 发送邮件 我做了类似的事情 backup current mail configs backup Conf
  • jQuery 在两个功能之间单击/切换

    我正在寻找一种方法 让两个单独的操作 函数 代码块 在单击某些内容时运行 然后在再次单击同一内容时运行完全不同的块 我把这个放在一起 我想知道是否有更有效 优雅的方式 我了解 jQuery toggle http api jquery co
  • Django excel save_book_to_database() 在使用 Django 1.8 的最新版本中损坏

    我一直在使用 Django 1 8 浏览 django excel 文档 但无法获得save book to database 上班 它要么默默地失败 要么给出以下错误 tuple object has no attribute meta
  • 标准和定制 GATT 特征

    我正在为 Android 手机和 Android 手表 wearOS 编写应用程序 这些应用程序将通过蓝牙相互通信 基本上Android手机上的应用程序将与WearOS设备绑定 然后与WearOS上的应用程序通信以启动指定功能 获取电池信息
  • 在 JavaScript 中使用 Pylons 全局变量(转义括号)

    我正在尝试访问 JavaScript 中 Python 全局变量中保存的字典中的结果 var selected jQuery target option selected text var list c persons by permiss
  • 如何定义/传递 sonata-admin 的实体管理器

    我跟着本教程 http symfony2 ylly fr sonataadminbundle fosuserbundle have a good base project jordscream 使用 FOSUserBundle 安装 Son
  • 恒定大小数组的运行中位数

    我正在尝试找到恒定大小数组的中位数 但数组总是在更新 我的意思是新号码被旧号码替换 我称这个过程为运行中位数 或者我们可以说动态中位数 这是我的代码 在代码内部 当 rand 函数生成 78 时 代码无法找到正确的中位数 78 41 67
  • 在recyclerview中notifydatachange期间保留连锁反应

    我开始修改我的应用程序以支持棒棒糖 基本上 我有一个带有 recyclerview 的文件浏览器片段 当用户打开这个片段时 他将看到其根目录上的所有文件夹 当用户单击该文件夹时 我需要获取所有子文件夹 文件并将它们显示给用户使用与notif
  • 当我尝试从列表中删除元素时,如何忽略 ValueError?

    如果我打电话 如何忽略 不在列表中 错误消息a remove x when x不在列表中a 这是我的情况 gt gt gt a range 10 gt gt gt a 0 1 2 3 4 5 6 7 8 9 gt gt gt a remov
  • cin >> num1, num2 有什么问题吗?

    include
  • SVG 在 Firefox 中渲染得很糟糕

    我正在制作带有滑动轮播的信息图表 li 我认为 尽管 FF 中 SVG 的错误已得到解决 但 SVG 在 Firefox 中显示为像素化 有人能看到这个问题的解决办法吗 URL http weaver wp weavertest com r
  • 克隆存储库而不将其设为原始远程存储库

    我正在从一台将被擦除的计算机上克隆一个 git 存储库 是否可以在不创建原始存储库的情况下克隆存储库origin master 或者我是否需要克隆它 然后删除远程分支 这是通过git remote rm origin Edit 存储库只有一
  • 如何使用 rspec 测试 ActionCable 和 Devise?

    在我的 Rails 5 1 应用程序中 我使用设备进行身份验证和 ActionCable 我的 ActionCable 连接如下所示 module ApplicationCable class Connection lt ActionCab
  • ImportError:在 Google 应用引擎中找不到 django.utils

    当我在 google app engine 项目中使用 django utils 中的 simplejson 时 出现此错误 Traceback most recent call last File base python27 runtim
  • 使用 Outlook 365 API 在组织中获取电子邮件的最佳方式

    我正在构建一个应用程序 用于从组织内部的电子邮件收集统计信息 我们假设这些组织使用 Outlook 365 我希望能够以最简单的方式执行以下操作 获取阅读组织中所有邮件的权限 获取电子邮件 附件并运行我的统计数据 Outlook 365 似
  • vim 退出时恢复 shell

    我刚刚在我的新计算机上安装了 Arch 但我不知道需要向 vimrc 添加什么命令 以便它在退出时恢复 shell 内容 在调用 vim 之前 也就是说 我希望我的 shell 看起来像这样 whoami root who root tty
  • 使用 Linq to Entities 查询创建 null ienumerable

    我正在开发一个使用实体框架的 ASP NET MVC 项目 我需要将从数据库中提取的值投影到PropertyValue类型 如下所示 public class PropertyValue public string StringValue
  • 将所有工作簿工作表复制到新工作簿 VBA

    我正在使用此代码将工作簿中的每张工作表复制到新工作簿中 它工作正常 但它颠倒了工作表的顺序 是否有办法阻止它这样做 Sub copy copies all the sheets of the open workbook to a new o
  • Java 数组操作

    我有一个名为 resize 的函数 它接受源数组 并将大小调整为新的宽度和高度 我认为我正在使用的方法效率低下 我听说有更好的方法可以做到这一点 无论如何 当scale是一个int时 下面的代码有效 然而 还有第二个函数称为 half 它使
  • Dart:如何在本机扩展中创建流

    在我的本机扩展中 我需要将整数流式传输到我的 Dart 控制台应用程序 在概念上非常相似 标准输入 如何创建向控制台应用程序公开的本机 Dart Stream 对象 我尝试为您创建一个示例并将其放在 github 上 https githu