- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
假设我想为具有大量依赖项的大型库中的特定函数创建一个 c# 包装器。为了争论,假设我想为 CGAL 中的 convex_hull_3
函数创建一个 C# 包装器。图书馆。顾名思义,这个函数为 3D 空间中的一堆点创建了一个凸包。您可能已经知道,CGAL 依赖于一些其他库,例如 Boost
MPFR
和 GMP
以及其他一些库(它动态链接到这些库).
您将如何创建这样的包装器?包装函数的正确方法是什么,以便最终包装器最大限度地减少暴露/包装的其他库的数量?
我能想到的一种解决方案:
用 C++ 创建一个网关 项目。该网关项目具有 CGAL 的 DLL 以及 CGAL 需要工作的所有其他内容(增强 DLL、MPFR 的 DLL 等)作为依赖项。该项目有 2 个文件:一个头文件和一个 CPP 文件。这些文件声明了一个函数(例如)createConvexHull
,它包装了原始的 convex_hull_3
。此外,createConvexHull
函数被标记为 __declspec(dllexport)
。
这个函数的要点是它改变了 CGAL 处理的数据的低级表示。例如,不必将点云数据声明为 CGAL 的内部数据类型之一,我们可以只传递一个表示 3D 数据 vector 的 double 组。因此,这个网关项目避免了包装 CGAL 的内部数据结构的需要,并暴露了最少量的额外依赖项。
将 gateway 项目构建到 DLL 文件中(例如 CGAL-gateway.dll)。
用 C# 创建一个项目。我们将此项目称为包装器项目,因为所有 P/Invoke 操作都将在该项目内执行。添加 CGAL-gateway.dll 作为对该项目的引用以及 Boost DLL、MPFR DLL 和 GMP DLL .在这个项目中写下所有的 P/Invoke 东西。
构建 wrapper 项目并将其添加为您希望具有创建凸包功能的任何其他 C# 项目的引用。
潜在问题:
首先,我不知道这是否是执行此类操作的标准方法。为了个人/教育目的,我一生只创建了 2 个包装器,所以我所知道的大部分都是通过反复试验和查看其他人的代码学到的。
我发现这种方法的一个问题是会有一个额外的 C++ 项目(我指的是 gateway 项目),它相对无用,只能用作抽象层。这种方法的另一个问题是它创建了一个 DLL hell 。要将我的 C# 包装程序交给其他人,我必须给他们 Boost、CGAL、MPFR 和 GMP DLL 也是如此。运行我的包装器可能需要大量的 DLL。老实说,我什至不知道是否有解决办法。
我在考虑静态链接而不是动态链接,但这里有两个考虑因素。首先,我以前从未尝试过静态链接。其次,我认为您不能静态链接到 GPL v3 库。因此,如果我决定将来在开源许可下发布我的包装器,我将不得不坚持 GPL v3 许可(这不是我想要的)。
我不知道我是否能够以易于理解的方式表达我的问题。如果问题需要任何澄清,请告诉我。
最佳答案
有多种方法可以为 C# 的 native 库创建包装器。以下是其中的一些:
1- 创建一个混合模式程序集,在其中将您需要的功能从您的 native 库包装到一个 C++/CLR 类中,该类可以直接在 C# 中使用。这种方法的缺点是 your C# project will now be CPU-architecture-specific (免责声明:此链接指向我根据 SO 中的一些帖子加上我自己的经验编写的内容)。在您的 C++/CLR 包装器中,您将有“机会”将 native C++ 类型(如 std::string)转换为 C# 可以理解的类型(如 System.String)。
2- 在 C++ 中创建一个 COM 库,该库也可以直接在 C# 中使用。如果您可以在系统中全局注册该库,那么您的 C# 应用程序不需要特定于 CPU 体系结构。同样在这种情况下,来自 .net 框架的 COM-Interop 引擎将为您执行大部分类型编码(marshal)处理。
3- 创建一个带有导出函数的常规动态库,该函数总结了您需要的功能并且可以使用 DllImport 从 C# 调用属性,或来自 Windows API 的 LoadLibrary/FreeLibrary/GetProcAddress 函数。我相信这就是您在问题中描述的方法,并且您添加了一个额外的 C# 包装器层,我认为最好将其作为示例代码/文档提供。
没有一种方法是对的或错的,在每一种方法中,您都可以动态或静态地链接其余的依赖项。
顺便说一句,如果你的依赖项被许可为 GPL-v3,我认为 there is no way for you to distribute these dependencies while complying with the GPL-v3 license .
关于c# - 为具有大量依赖项的库创建包装器的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33639992/
我在 gobject 上阅读了一个维基百科页面,上面写着, Depending only on GLib and libc, GObject is a cornerstone of GNOME and
如何注册一个依赖属性,其值是使用另一个依赖属性的值计算的? 由于 .NET 属性包装器在运行时被 WPF 绕过,因此不应在 getter 和 setter 中包含逻辑。解决方案通常是使用 Proper
我一直在尝试将 ActionbarSherlock maven 依赖项添加到我的项目中 com.actionbarsherlock library 4.2.0 在我的 po
http://tutorials.jenkov.com/ood/understanding-dependencies.html#whatis说(强调我的): Whenever a class A us
我对所有这些魔法有点不清楚。 据我了解,依赖属性是从 DependencyObject 继承的,因此存储值: 如果分配了值(在本地字典中),则在实例本身中 或者如果未指定值,则从指向父元素的链接中获取
我刚刚更新了在 ASP.NET Framework 4.5.2 版上运行的 MVC Web 应用程序。我正在使用 Twilio 发送 SMS 消息: var twilio = new TwilioRe
我刚刚发现了一件令人生畏的事情。 spring 依赖坐标有两个版本。 项目依赖于 spring mvc 和 spring flow。有两组并行的依赖项。 Spring MVC 具有以下方案的依赖项
我正在尝试包含 的 maven 依赖项 org.jacorb jacorb 2.3.1 依赖已解决,但它导致另一个依赖 picocontainer 出现问题: [ERROR
我正在尝试在 Haskell 项目中包含特定版本的库。该库是住宿加早餐型的(用于 martix 操作),但我需要特定的 0.4.3 版本,该版本修复了乘法实现的错误。 所以,我的 stack.yaml
有谁知道如何制作依赖的 UIPickerView.例如,当我选择组件一的第 2 行时,组件二的标题会发生变化吗? 我在互联网上查找过,没有真正的答案,我尝试过使用 if 和 switch 语句,但它们
我正在编写一个用于验收测试的项目,由于各种原因,这依赖于另一个打包为 WAR 的项目。我已成功使用 maven-dependency-plugin 解压 WAR,但无法让我的项目包含解压的 WEB-I
或多或少我在 session 上大量构建我的网站(特别是重定向用户等),我很好奇这是否是一种危险的做法。禁用浏览器 cookie 保存的用户的大致比例是多少?我愿意接受任何建议:) 谢谢 最佳答案 s
开始玩 Scala futures,我被依赖的 futures 困住了。 让我们举个例子。我搜索地点并获得 Future[Seq[Place]]。对于这些地点中的每一个,我搜索最近的地铁站(该服务返回
或多或少我在 session 上大量构建我的网站(特别是重定向用户等),我很好奇这是否是一种危险的做法。禁用浏览器 cookie 保存的用户的大致比例是多少?我愿意接受任何建议:) 谢谢 最佳答案 s
我有一个二进制文件,需要一些 *.so 文件才能执行。现在,当我尝试在一些旧机器上执行它时,它会显示 /lib/libc.so.6: version `GLIBC_2.4' not found 如何将
我尝试使用 Dygraph 来表示图表,我在 https://github.com/danvk/dygraphs 中找到了代码,但是它有太多的依赖文件,我觉得很烦人。是否有一个文件可以容纳所有必需的
我正在处理一个 javascript 文件,该文件 a) 声明一个具有函数的对象,并且 b) 使用它期望在外部声明的散列调用该对象的 init 函数。我的 Jasmine 规范提示它找不到哈希,因为它
最近我一直在学习 Angular 并且进展顺利,但是关于依赖注入(inject)的一些事情我仍然不清楚。 是否有任何理由在我的 app.js 文件中声明我的应用程序的其他部分(服务、 Controll
考虑一个名为 foo 的表,它有 id (PRIMARY & AUTO_INCREMENT) 列。我正在向该表中插入一行,挑战从此时开始。 $db->query("INSERT INTO `foo`
我正在使用级联下拉 jquery 插件。 (https://github.com/dnasir/jquery-cascading-dropdown) 我有两个下拉菜单。 “客户端”和“站点”。 根据您
我是一名优秀的程序员,十分优秀!