在 Node.js / 服务器端 JavaScript 中使用 .NET DLL

61

我有一个宠物项目,是一个在线游戏,整个游戏引擎都是用C#编写的,我想知道是否有办法可以从使用Node.JS、Socket.IO、Express等构建的解决方案中调用这个现有程序集(.dll)的函数?

游戏引擎本身非常完整;经过测试和稳定。我希望有一种简洁的方式能够公开其功能而不会增加太多开销。

更新:

为了回答自己的问题... 我最终构建了自己的Web Socket服务器(基于最新的Web Socket协议文档)。它是用C#编写的,并使用Mono编译,以便可以在运行Mono的Linux盒子上托管,因此(通过一些调整),我可以使用我的现有游戏引擎。

更新2 现在有一个项目正好符合我最初的要求 - http://tjanczuk.github.io/edge/#/

更新3 Edge.js支持node的最新版本和.net core,有一个新的edge-js包。

支持Node.Js 6.x、7.x、8.x、9.x、10.x、11.x,在Windows/Linux/macOS上支持.NET Core 1.0.1 - 2.x。支持Mono运行时4.8.x - 5.x。

可以从https://www.npmjs.com/package/edge-js安装。


@Dve:我现在跟你差不多处境。编写自己的 Web Socket 服务器困难吗?我在考虑是否也应该尝试一下,或者看看现有的 C# Web 服务器。但更重要的是,你最终在客户端方面是怎么做的?你只是向自己的自定义服务器发送 Ajax 请求,还是继续使用 node.js/socket.io 客户端向服务器发送请求? - mpen
@Mark 项目曾经被搁置,但现在得以重新启动,这要感谢 iisnode 项目 - https://github.com/tjanczuk/iisnode - David
@Dve 我也在同样的路上。我对edge还很陌生。你是如何从nodejs中创建对象等内容的? - TomO
8个回答

30

请查看我开始的edge.js项目(http://tjanczuk.github.com/edge)。它提供了一种在进程内运行.NET和node.js代码的机制。Edge.js允许你从node.js调用.NET代码,也可以从.NET调用node.js代码。它不仅可以在.NET和node.js之间传输数据,还可以协调多线程CLR和单线程V8之间的线程模型。

使用edge.js,你可以从node.js中访问预先存在的.NET代码,这似乎符合你的场景。


感谢这个有用的Edge Node.js模块。我可以使用它来调用ProtectedData.Unprotect API来读取安全配置。 - Sushil
我真的在努力寻找一个导入 DLL 并使用 edge-js 运行其方法的工作示例... 有什么帮助吗? - john k
6
这个项目已经停止了,我在构建适用于node v15的版本时遇到了问题。 - Epic Speedy

27

最近我也遇到了同样的挑战(需要从node.js的javascript调用C#代码)。我有数千行复杂的C#代码,真的不想将其移植到javascript。

我的解决方法如下:

  • 相关的C#代码基本上是DLL程序集中的1-2个类
  • 定义了一个COM接口,该接口是C#类接口的子集,并在C#类中实现了该接口。因此,该DLL成为了一个进程内COM服务器。
  • 实现了一个node.js扩展DLL,使用标准Win32 COM API实例化我的C# COM类,并使用COM接口将来自node.js javascript的方法调用路由到C#代码。

如果只想进行单向调用,则此解决方法可以解决问题。我还需要从C#向javascript发出调用的要求。这更难实现。以下是具体步骤:

  • 在node.js扩展DLL中实现一个COM对象(ATL在这里有帮助)
  • 将此COM对象的接口引用传递给C#代码(COM Interop)
  • 通过COM对象将调用路由到node.js中的V8对象

也许我会抽出一些额外时间,将此作为示例项目。


2
如果你能提供一个例子就太好了...不过,还是点赞鼓励。 - Ege Özcan
+1 - 如果您有时间,一份逐步教程将会非常棒。 - Brandon Boone
1
还有一个问题,我已经按照你说的做了,准备好模块后卡住了。我收到以下错误信息: Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'My file with COM interface' or one of its dependencies. The system cannot find the file specified. 如果能提供一段代码就太感激了。 - blueomega

18

如果你只想启动一个轻量级的HTTP服务器,同时使用C#和.Net进行编程,那么你可以尝试使用Kayak。它是一个C#的轻量级HTTP服务器,行为类似于node.js。

kayakhttp

更新:

如果你正在寻找一个轻量级的HTTP服务器来处理web请求,现在有几个备选方案:

  • ServiceStack(推荐)
  • Microsoft WebAPI
  • NancyFx

据我所知,以上所有方案都可以在某些版本的Mono上运行,因此你仍然可以将它们部署在基于Windows和Unix的系统上。


更新此答案。现在您不必使用Kayak,可以使用随较新版本的ASP.Net一起提供的WebAPI。 - Khalid Abuhakmeh
链接失效了 :( 看起来域名抢注者占据了它。 - Mark McDonald

8
.Net插件可以编写,简单来说,您可以编写一个常规的本机插件,并通过CLI/C ++调用添加.Net调用到.Net dlls中。
在实践中,通常创建一个C# dll库,然后从CLI/C++节点插件项目中调用它。有一些细节需要注意,例如确保实际的节点插件定义文件在没有CLR支持的情况下编译,以便节点可以正确加载它。
您可以查看:https://github.com/saary/node.net 了解如何实现此操作的示例。

1
只有链接的答案如果链接页面消失可能会不太有帮助。你能像其他回答一样简要概括一下吗? - Kate Gregory
-1 node.net是一个误导。请检查最后一步:“将“公共语言运行时支持”选项更改为无公共语言运行时支持”。换句话说,没有CLR。 - Evgeniy Berezovsky
这绝对不是一个误导。最后一步讲到的是 node.js 插件绑定文件,这是唯一一个在没有 CLR 支持的情况下编译的文件(这完全合理,因为 node.js 是本地的)。 - saary
@saary 你说得完全正确。我应该更仔细地阅读。请原谅我的错误。取消减1! - Evgeniy Berezovsky

6
以下回答已经过时,但仍有助于理解Node.js从一开始的内容。现在Node.js也可以在nodejs.org上原生地提供给Windows使用,无需cygwin或其他软件。
首先,目前还没有原生的Node.js Windows版本,只有一个cygwin版本(但我猜你已经知道了)。
在GitHubs的某个地方有一个Node模块,提供了调用本地库的包装器,但是如果我没记错的话,它只能与.so库一起工作。
因此,如果您想使用C# DLL,则首先必须编写一个本地Node.js扩展作为接口: https://www.cloudkick.com/blog/2010/aug/23/writing-nodejs-native-extensions/ 从该扩展中,您必须加载DLL并将来自Node.js的调用封装到C#代码中,这意味着您必须编写一些低级C/C++代码并将C#值转换为V8内容。
我只有C++和V8的经验,开始有些困难,因为代码示例不够丰富,同时封装C++类也并不是那么简单。但我写了一个小型JS游戏引擎,使用了C++ OpenGL后端,它还没有完成(几乎没有注释),但可能会给你一些想法。 注意: 在野外有一些项目提供对V8包装器的某种自动生成,但这些仅限于C++。
综上所述,我认为将C#包装器工作起来会很有冒险精神,但应该是可行的。

对于你的回答慢了一些,我很抱歉。感谢提供信息,不过尽管它很有趣,但看起来太混乱了,而这正是我一直试图避免的。我越看项目越觉得后悔在C#中编写整个游戏引擎,现在似乎限制了我的选择! - David
3
不再准确。Node现在已经原生支持Windows了。 - rainabba

3
新的 edge-js 包支持 node 最新版本和 .net core。支持 Node.Js 6.x, 7.x, 8.x, 9.x, 10.x, 11.x,以及 Core 1.0.1 - 2.x 在 Windows/Linux/macOS 上的运行。同时也支持 Mono 运行时版本 4.8.x - 5.x。可以通过 (npm i edge-js) 在https://www.npmjs.com/package/edge-js上获取安装。

2
你可能会在这个项目中有所收获,它是将Node.js移植到.NET的一个版本。虽然我自己没有使用过,但理论上,使用本地的.NET实现,你应该能够做到你需要的一切。
你也可以尝试将你的C#游戏引擎移植到Mono上,并构建包装器。

这是另一个值得一试的项目,类似于上面的海报,但在V8上运行。 - gatapia

1

我知道这是一个旧问题,但是我想提供一个最新的答案。在IIS 7.5和.Net 4.x中支持Websockets,但使用SignalR库很可能是最简单的方法。这类似于NodeJS的socket.io库。

至于通过NodeJS访问.Net代码,您最好的选择是Edge.js,使用C / C ++构建混合本机程序集,通过命令行应用程序(最好使用输入/输出管道)或通过服务(TCP或其他)公开您的.Net代码。

我认为Edge.js非常有限,没有比管道控制台接口更多的优势...如果您需要更复杂的接口,则可能最好使用服务。此时,除非你在NodeJS上有投资,否则最好在.Net上继续整个项目,以免出现困难。


说实话,我是NodeJS的忠实粉丝,但在使用它时我会非常务实。 - Tracker1
很好的建议。看到对一个旧问题的更新(但仍然有效和相关)总是很不错的。 - Troy Gizzi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接