我打算编写一个应该可以被广泛的平台上的大量人使用的库。我需要考虑什么来设计它?为了使这个问题更具体,最后有四个“子问题”。
考虑到所有已知的要求和细节,我得出结论,用C或C ++编写的库是可行的方法。我认为我的库的主要用途是在用C,C ++和Java SE编写的程序中,但我也可以考虑从Java ME,PHP,.NET,Objective C,Python,Ruby,bash scrips中使用它的原因,等等......也许我无法针对所有这些,但如果有可能,我会做到的。
在这里描述我的库的全部目的将是很多,但有些方面可能对这个问题很重要:
当然,无论答案是满足我的具体要求,还是以一般方式回答问题,对更广泛的受众都有帮助,我们都欢迎回答!
以下是我在过去几个月收集的一些假设和结论:
大多是正确的。直接的程序界面是最好的。 (这与C btw(**)不完全相同,但足够接近)
我接口DLL很多(*),包括开源和商业,所以这里有一些我记得日常练习的要点,请注意这些是更值得研究的推荐区域,而不是基本的事实:
(**)这是因为“C”意味着二进制仍然依赖于使用的C编译器,特别是如果没有真正的通用系统ABI。想想像这样的东西:
=====自动标头转换====
虽然我不太了解SWIG,但我知道并使用了一些特定于delphi的头文件工具(h2pas,Darth / headconv等)。
但是我从不在全自动模式下使用它们,因为更常见的是输出很少。注释更改行或被剥离,并且不保留格式。
我通常制作一个小脚本(在Pascal中,但你可以使用任何具有良好字符串支持的东西)将头部分开,然后在相对同质的部分上尝试工具(例如,只有结构,或者只定义等)。
然后我检查我是否喜欢自动转换输出,并使用它,或者尝试自己制作一个特定的转换器。由于它适用于子集(仅限于结构),因此通常比制作完整的标头转换器更容易。当然,这取决于我的目标是什么。 (漂亮,可读的标题或快速和脏)。在每一步,我可能会做一些替换(使用sed或编辑器)。
我为Winapi commctrl和ActiveX / comctl标头做的最复杂的方案。在那里我结合了IDL和C头(接口的IDL,C中的一堆不可解析的宏,其余的C头),并设法获得大约80%的宏类型(通过传播sendmessage中的类型转换)宏返回宏声明,有合理的(wparam,lparam,lresult)默认值)
半自动方式的缺点是声明的顺序不同(例如,第一个常量,然后是结构,然后是函数声明),这有时会使维护变得困难。因此,我始终保持原始标题/ sdk与之比较。
Jedi winapi转换项目可能有更多的信息,他们将大约一半的Windows标题翻译成Delphi,因此拥有丰富的经验。
我不知道但是如果它适用于Windows那么你可以尝试直接的类似C的API(类似于WINAPI),或者将你的代码打包为COM组件:因为我猜想编程语言可能希望能够调用Windows API和/或使用COM对象。
关于自动包装器生成,请考虑使用SWIG。对于Java,它将完成所有JNI工作。此外,它能够正确地转换复杂的OO-C ++接口(前提是您遵循一些基本准则,即没有嵌套类,没有过度使用模板,加上Marco van de Voort提到的那些)。
想想C,别的什么。 C是最流行的编程语言之一。它广泛用于许多不同的软件平台,并且很少有计算机体系结构不存在C编译器。所有流行的高级语言都提供了C语言的接口。这使得您的库几乎可以从现有的所有平台访问。不要过分担心提供面向对象的界面。在C,OOP中完成库之后,可以使用适当的客户端语言创建功能或任何其他样式界面。没有其他系统编程语言可以为您提供C的灵活性和可维护性。
我认为NestedVM会比纯Java慢,因为int [] []上的数组边界检查表示MIPS虚拟机内存。这是一个很好的概念,但现在可能表现不佳(直到手机制造商添加NestedVM支持(如果他们这样做),大多数东西现在都是缓慢的,n'est-ce pas)?虽然它可以在没有错误的情况下解压缩JPEG,但速度也不容小觑! :)
你写的东西中没有别的东西可以说出来,这并不是说它是对还是错!原则听起来(主要是听说单词和语言的选择,说实话),就像大致标准的最佳实践,但我没有仔细考虑你所说的一切细节。正如你自己所说,这真的应该是几个问题。但是当然做这种事情并不是很容易,因为你已经修复了可能与你工作过的最后一个代码库略有不同的架构......! ;)
我的想法:
您对C接口兼容性的所有评论对我来说都是合理的,除了您似乎没有正确解决内存管理策略之外,这几乎是最好的做法 - 有些句子有点含糊不清/模糊/错误听起来。内存管理的设计在很大程度上取决于应用程序中的访问模式,而不是功能本身。我想你研究别人试图制作标准ANSI C API,Unix API,Win32 API,Cocoa,J2SE等便携式接口的尝试。
如果是我,我会在常规Java和Davlik虚拟机Java的常用元素的精心选择的子集中编写库,并编写我自己的自定义解析器,将代码转换为C,用于支持C的平台,当然是大多数人。我建议如果你限制自己使用各种大小的int,bools,字符串,字典和数组的数据类型,并仔细使用它们,这将有助于跨平台问题,而不会在大多数情况下影响性能。
你的假设似乎没问题,但我看到了前方的麻烦,你已经在你的假设中发现了很多。正如你所说,你无法真正导出c ++类和方法,你需要提供一个基于函数的c接口。无论你构建什么外观,它都将是一个基于功能的界面。
我看到的基本问题是人们选择特定语言及其运行时因为他们的思维方式(功能或面向对象)或他们解决的问题(网络编程,数据库......)以某种方式对应于该语言或其他。在c中实现的库可能永远不会像他们习惯使用的库那样,除非他们自己编程。就个人而言,当我使用python时,我总是更喜欢“感觉像python”的库,而当我使用Java EE时,我总是喜欢感觉像java的库,即使我知道c和c ++。
因此,您的努力可能几乎没有实际用途(除了您获得的经验),因为人们可能希望坚持他们的思维方式,而是重新实现功能,而不是使用完成工作但不适合的库。
我也担心理想的可移植性会严重妨碍开发。只需考虑所需的无限构建设置,并对其进行测试。我曾经研究过一个试图保持5个操作系统兼容性的项目(所有类似posix,但仍然如此)和大约10个编译器,这些构建是测试和维护的噩梦。
给它一个XML接口,无论是作为参数传递还是返回值,还是通过命令行调用传递给文件。这可能看起来不像普通的函数接口那样直接,但是从例如Java访问可执行文件的最实用的方法。