【问题标题】:Referencing Google's V8 engine from a .NET app从 .NET 应用程序引用 Google 的 V8 引擎
【发布时间】:2010-09-26 07:07:23
【问题描述】:

我正在构建一个 .NET 3.5 应用程序,并且需要在服务器上评估 JS 代码 - 基本上是用户提供的可以在浏览器或服务器上工作的规则集。托管 JS 不是一个选项,因为 JS 代码将在运行时提供。 Aptana 的 Jaxer 也不是一个选择。所以我正在考虑在我的应用程序中使用 V8 引擎的构建。

我成功地将源代码构建到 DLL 中,但该 DLL 不是托管库,也不是 COM。 V8 只是普通的 C++。

关于如何在 C# 中与这种类型的 DLL 互操作有什么想法吗?另外,我对 SpiderMonkey 或其他 JS 引擎的其他建议持开放态度。

提前致谢。

更新:

我能够使用 Ryan 的解决方案。我刚刚更新了对来自主干的最新构建的引用。效果很好。谢谢瑞恩。

【问题讨论】:

  • 顺便说一句,我在哪里可以获得已编译 DLL 的副本? (由于懒得自己编译,主要是我没有设置VS做C++)
  • 我已经更新了我的帖子,提供了一个链接来下载我创建的测试项目。
  • 对于那些刚刚找到这个页面的人来说,现在 Codeplex 也有 V8.NET。
  • v8dotnet.codeplex.com Codeplex 的 V8.NET
  • V8.Net 现在在 NuGet 上,并且支持 .Net 标准! :) (nuget.org/packages/V8.Net)

标签: .net javascript interop v8 serverside-javascript


【解决方案1】:

由于这个问题是不久前发布的,我想我会提供一些更新。

微软制作了ClearScript脚本引擎,支持V8、JScript和VBScript。

您可以轻松添加控制台等 C# 类型并在脚本中使用它。 添加 WPF 按钮类型并创建一个也没有问题。 github中有一些很好的例子,所以我建议任何阅读这篇文章的人快速浏览一下。

【讨论】:

    【解决方案2】:

    您也可以尝试 V8.NET。

    https://www.nuget.org/packages/V8.Net/

    与许多其他包装器相比,它允许您轻松地将代码与 V8 集成。它还支持 .Net 4.6.1+ 和 .Net Standard 2.0+ (.Net Core)。

    【讨论】:

      【解决方案3】:

      我意识到这可能不是您问题的确切答案,但我想我会投入 2 美分,因为我怀疑很多人都尝试过。

      我通过使用混合模式 C++ 创建了一个托管包装器来使其工作。还有其他方法可以做到这一点,但我将尝试制作一个可以在任何 .NET 语言中使用的完整包装器。

      让 lib 以一种可以包含在混合模式项目中的方式进行编译有点挑战。我不得不修改用于 /MD 和 /MDd 的运行时库(在 SConstruct 文件中),以便它与 /clr 开关兼容。

      到目前为止,我只运行了简单的脚本,因为我还没有实现回调、自定义方法、对象等。

      以下是我的一个测试应用的使用情况的快速示例:

      V8DotNet.Shell shell = new V8DotNet.Shell();
      
      shell.ExecuteScript(@"print('V8 version is: ' + version());");
      

      它也可以运行更复杂的脚本,例如 base64 编码器。但目前我只能从 c++ 端添加自定义项。

      如果有人感兴趣,我愿意提供更多信息 + 代码,因为我可能永远不会选择这个项目。但是,我担心这里的帖子要写很多代码,所以我们必须找到其他媒体,比如 google code 或 codePlex。

      编辑:


      好的,我已经上传了代码。我必须对此发表免责声明:这个项目还很早,我充其量只是 C++ 的业余爱好者,所以不要抱太大希望。另外,这个项目是在 chrome 发布之后创建/完成的,所以包含的 v8 版本可能是旧的。

      也就是说,这里是:http://ryanscook.com/Files/V8-DotNet.zip (21.5 MB)

      在包装中,您会发现以下感兴趣的物品:

      V8Net-Library\V8.Net\V8.Net.sln - 这个 是具有托管的解决方案 C++ 包装器项目和 C# 控制台应用程序 用于测试。

      Dependencies\V8 - 这是我的 V8 代码 我用来构建 V8 库的。

      希望对你有帮助!

      【讨论】:

      • “我必须修改用于 /MD 和 /MDd 的运行时库(在 SConstruct 文件中),以便它与 /clr 开关兼容。” - 不是一个非常艰巨的挑战! :)
      • 很好地找到了我们必须做的事情。打字总是最容易的部分。我想我缺乏 C++ 经验让我有点沮丧。
      • 瑞恩:感谢您的帮助。我想使用 /clr 开关进行构建 - 就像您所做的那样。我对 Scons 没有任何经验。请让我更详细地了解您对 SConstruct 文件所做的更改。特别是在您指定 /clr 开关的地方。此外,对于共享库,/MD 似乎已被使用。提前感谢您的帮助。
      • 老实说,我不记得我的 v8 版本的确切细节。 /clr 在包装库中。基本上我必须创建一个稍作修改的 v8.lib,以便我可以将它链接到我的混合模式 dll。今天我会找时间把项目贴在某个地方供你下载。
      • Ryan:见我上面的更新。您的代码适用于来自主干的最新版本。谢谢。
      【解决方案4】:

      死灵术。
      根据 2018 年和 .NET Core 2.0+
      你可以使用vroomjs-core

      执行一些Javascript:

      using (var engine = new JsEngine())
      {
          using (var context = engine.CreateContext())
          {
              var x = (double)context.Execute("3.14159+2.71828");
              Console.WriteLine(x);  // prints 5.85987
          }
      }
      

      创建并返回一个 Javascript 对象,然后调用它的方法:

      using (JsEngine js = new JsEngine(4, 32))
      {
          using (JsContext context = js.CreateContext())
          {
              // Create a global variable on the JS side.
              context.Execute("var x = {'answer':42, 'tellme':function (x) { return x+' '+this.answer; }}");
              // Get it and use "dynamic" to tell the compiler to use runtime binding.
              dynamic x = context.GetVariable("x");
              // Call the method and print the result. This will print:
              // "What is the answer to ...? 42"
              Console.WriteLine(x.tellme("What is the answer to ...?"));
          }
      }
      

      从 Javascript 访问 CLR 对象的属性和调用方法:

      class Test
      {
          public int Value { get; set; }
          public void PrintValue(string msg)
          {
              Console.WriteLine(msg+" "+Value);
          }
      }
      
      using (JsEngine js = new JsEngine(4, 32))
      {
          using (JsContext context = js.CreateContext())
          {
              context.SetVariable("m", new Test());
              // Sets the property from Javascript.
              context.Execute("m.Value = 42");
              // Call a method on the CLR object from Javascript. This prints:
              // "And the answer is (again!): 42"
              context.Execute("m.PrintValue('And the answer is (again!):')");
          }
      }
      

      【讨论】:

        【解决方案5】:

        我猜 gatapia 已经用 jish 替换了 js.net

        【讨论】:

          【解决方案6】:

          你可以试试 Javascript .NET:

          http://javascriptdotnet.codeplex.com/

          它允许您从 .NET 创建 V8 上下文并在其中注册 CLI 对象,以便您可以操作它们并从 Javascript 代码调用成员。它在运行时编译 Javascript。

          检查一下。

          【讨论】:

          • 不错,很酷,但是非常不适合服务器端使用。因为 V8 引擎不是线程安全的。 (请参阅:javascriptdotnet.codeplex.com/workitem/7062)这太糟糕了..
          • javascriptdotnet 现在是线程安全的。 v8 的多个实例(隔离)可以同时运行,但它们不能交互。
          【解决方案7】:

          查看v8sharp。它支持在 .NET 应用程序中执行 JS。它还允许您使用 v8 引擎注册 .NET 类型,以便您的 JS 代码可以与您的 .NET 代码交互。我正在添加对挂钩函数/委托支持的支持。

          【讨论】:

          • v8sharp 很棒,我在我的项目中使用过。
          【解决方案8】:

          Microsoft are building a real javascript - not "JScript" - runtime(以及 IronPython、IronRuby 和 VB10)在 CLR 上使用 DLR,但我找不到任何下载或内容。也许这将在 C# 4 中出现?

          【讨论】:

          • 是的,不久前我听说过 JS DLR 实现,所以我首先研究了它。但是,不幸的是,MSFT 似乎还没有为 JS 发布任何东西,只有 IronPython。无赖。
          • DLR 上的托管 JavaScript 已失效。看到这个答案:code.google.com/apis/v8/design.html
          • 我不明白 V8 设计文档与 DLR 上的 Javascript 有什么关系? DLR 上 javascript 的意义不仅仅在于纯粹的速度(尽管那将是一个不错的奖励),还在于与现有的 .NET 生态系统进行干净的互操作,而 V8 没有这样做
          【解决方案9】:

          据我所知,使用 IJW(托管 C++)编译它应该可以工作 - 但我可能真的错了,我从未接触过 MC++。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-08-11
            • 2019-11-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-12-16
            相关资源
            最近更新 更多