如何设计一个可以在许多客户端语言中使用的C / C ++库?

时间:2009-12-19 13:09:46

标签: c++ c portability

我计划编写一个应该可以被广泛平台上的大量人使用的库。我需要考虑什么来设计它?为了使这个问题更具体,最后有四个“子问题”。

语言选择

考虑到所有已知的要求和细节,我得出结论,用C或C ++编写的库是可行的方法。我认为我的库的主要用途是用 C,C ++和Java SE 编写的程序,但我也可以考虑从 Java ME,PHP,.NET中使用它的原因。目标C,Python,Ruby,bash scrips等...... 也许我无法针对所有这些目标,但如果可能的话,我会做的。

要求

在这里描述我的图书馆的全部目的会有很多,但有些方面可能对这个问题很重要:

  • 图书馆本身起初很小,但肯定会变得极其复杂,因此不能同时维护多个版本。
  • 大部分复杂性将隐藏在库中,但
  • 该库将构建一个在内部大量使用的对象图。库的某些客户端只对特定对象的特定属性感兴趣,而其他客户端必须以某种方式遍历对象图
  • 客户可以更改对象,并且必须通知库
  • 库可能会更改对象,如果客户已有该对象的句柄,则必须通知客户
  • 库必须是多线程的,因为它将维护与其他几个主机的网络连接
  • 虽然可以同步处理对库的一些请求,但其中许多请求将花费太长时间并且必须在后台处理,并在成功(或失败)时通知客户

当然,无论答案是否符合我的具体要求,或者他们是否以更广泛的方式回答问题的一般方式回答问题,欢迎回答!

我的假设,到目前为止

以下是我在过去几个月收集的一些假设和结论:

  • 在内部,我可以使用我想要的任何东西,例如带有运算符重载,多重继承,模板元编程的C ++ ......只要有一个处理它的可移植编译器(想想gcc / g ++)
  • 但我的界面必须是一个干净的C界面,不涉及名称修改
  • 另外,我认为我的界面应该只包含函数,基本/原始数据类型(可能是指针)作为参数传递并返回值
  • 如果我使用指针,我想我应该只使用它们将它们传回库中,而不是直接在引用的内存上运行
  • 对于在C ++应用程序中的使用,我可能还提供面向对象的接口(也容易出现名称错误,因此App必须使用相同的编译器,或者以源代码形式包含库)
  • 在C#中使用是否也是如此?
  • 在Java SE / Java EE中使用时,Java本机接口(JNI)适用。我有一些关于它的基本知识,但我绝对应该仔细检查它。
  • 并非所有客户端语言都能很好地处理多线程,因此应该有一个线程与客户端进行通信
  • 在Java ME上使用时,没有JNI这样的东西,但我可能会选择Nested VM
  • 要在Bash脚本中使用,必须有一个带命令行界面的可执行文件
  • 对于其他客户端语言,我不知道
  • 对于大多数客户端语言,使用该语言编写适配器接口会很好。我认为有一些工具可以自动为Java和其他一些人生成这个
  • 对于面向对象的语言,有可能创建一个面向对象的适配器,它隐藏了库的接口是基于函数的事实 - 但我不知道它是否值得努力

可能的子问题

  • 这可以通过可管理的努力来实现,还是可移植性太高?
  • 有关于此类设计标准的好书/网站吗?
  • 我的任何假设都错了吗?
  • 哪些开源库值得学习从他们的设计/界面/源中学习?
  • meta:这个问题相当长,你有没有办法将它分成几个较小的? (如果您回复此问题,请将其作为评论,而非答案)

7 个答案:

答案 0 :(得分:30)

答案 1 :(得分:4)

我不知道但是如果它适用于Windows,那么您可以尝试使用类似于C的直接API(类似于WINAPI),或将代码打包为COM组件:因为我猜测编程语言可能需要能够调用Windows API和/或使用COM对象。

答案 2 :(得分:3)

关于自动包装器生成,请考虑使用SWIG。对于Java,它将完成所有JNI工作。此外,它能够正确地转换复杂的OO-C ++接口(假设您遵循一些基本准则,即没有嵌套类,没有过度使用模板,加上Marco van de Voort提到的那些)。

答案 3 :(得分:3)

想想C,别的什么。 C是最流行的编程语言之一。它广泛用于许多不同的软件平台,并且很少有计算机体系结构不存在C编译器。所有流行的高级语言都提供了C语言的接口。这使得您的库几乎可以从现有的所有平台访问。不要过分担心提供面向对象的界面。在C,OOP中完成库之后,可以使用适当的客户端语言创建功能或任何其他样式界面。没有其他系统编程语言能够为您提供C的灵活性和可维护性。

答案 4 :(得分:2)

NestedVM我认为比纯Java慢,因为int [] []上的数组边界检查表示MIPS虚拟机内存。它是一个非常好的概念,但现在可能表现不佳(直到手机制造商添加NestedVM支持(如果他们这样做),大多数东西现在都会变慢,不需要PAS)?虽然它可以在没有错误的情况下解压缩JPEG,但速度也不容小觑! :)

你写的东西中没有别的东西可以说出来,这并不是说它是对还是错!原则听起来(主要是听说单词和语言的选择,说实话),就像大致标准的最佳实践,但我没有仔细考虑你所说的一切细节。正如你自己所说,这真的应该是几个问题。但是当然做这种事情并不是很容易,因为你已经修复了可能与你工作过的最后一个代码库略有不同的架构......! ;)

我的想法:

您对C接口兼容性的所有评论对我来说都是合理的,除了您似乎没有正确解决内存管理策略之外,这几乎是最好的做法 - 有些句子有点含糊不清/模糊/错误听起来。内存管理的设计在很大程度上取决于应用程序中的访问模式,而不是功能本身。我认真研究其他人尝试制作标准ANSI C API,Unix API,Win32 API,Cocoa,J2SE等便携式接口的尝试。

如果是我,我会在常规Java和Davlik虚拟机Java的常用元素的精心选择的子集中编写库,并编写我自己的自定义解析器,将代码转换为C,用于支持C的平台,这当然是他们中的大多数。我建议如果你限制自己使用各种大小的整数,bool,字符串,字典和数组的数据类型,并仔细使用它们,这将有助于跨平台问题,而不会在大多数情况下影响性能。

答案 5 :(得分:2)

你的假设似乎没问题,但我看到了前方的麻烦,你已经在你的假设中发现了很多。 正如你所说,你无法真正导出c ++类和方法,你需要提供一个基于函数的c接口。无论你构建什么外观,它都将是一个基于功能的界面。

我看到的基本问题是人们选择特定语言及其运行时因为他们的思维方式(功能或面向对象)或他们解决的问题(网络编程,数据库......)对应于该语言以某种方式或其他方式。 在c中实现的库可能永远不会像他们习惯使用的库那样,除非他们自己编程。 就个人而言,当我使用python时,我总是更喜欢一个“感觉像python”的库,而当我使用Java EE时,我总是更喜欢java,即使我知道c和c ++。

因此,您的努力可能几乎没有实际用途(除了您获得的经验),因为人们可能希望坚持他们的思维方式,而是重新实现功能而不是使用完成工作的库,但是不适合。

我还担心所需的可移植性会严重妨碍开发。只需考虑所需的无限构建设置,并对其进行测试。我曾参与过一个试图保持5个操作系统兼容性的项目(所有类似posix,但仍然如此)和大约10个编译器,这些构建是测试和维护的噩梦。

答案 6 :(得分:0)

为它提供一个XML接口,无论是作为参数传递还是返回值,还是通过命令行调用传递给文件。这可能看起来不像普通的函数接口那样直接,但却是从Java等访问可执行文件的最实用的方法。