使用 ooc/接口进行编程
ooc 的一个强项是它对 C 库的描述性接口方式。这些接口可以像 extern 函数列表一样低级,也可以通过将函数调用和数据封装在 ooc 类或复杂的覆盖层中而变得“高级”。
在接下来的讨论中,我们将构建一个对 libYAML (http://pyyaml.org/wiki/LibYAML) 库的基本接口。nddrylliog 已经创建了一个现有接口 在这里,我们将把它作为参考。
我们的大部分工作将涉及读取库头文件 (http://svn.pyyaml.org/libyaml/branches/stable/include/yaml.h) 以及决定如何使用其中的内容。要与 C 库进行接口,我们需要它存在于我们的系统中。我们还希望为我们的新接口创建一个文件层次结构。
在本节中,我们将使 C 库对我们的新 ooc 接口可见,并为该接口创建文件层次结构。
安装(使 C 库可用)是与系统相关的。以下步骤适用于 Ubuntu 用户
sudo apt-get install libyaml-dev
另一个选项(这实际上超出了本书的范围)是在用户帐户内保留库,并控制 C 编译器搜索库和头文件的路径。使用 ~/local 作为前缀的示例设置可能是
mkdir ~/local
cd ~/local
wget http://pyyaml.org/download/libyaml/yaml-0.1.4.tar.gz
tar -xzvf yaml-0.1.4.tar.gz
cd yaml-0.1.4
./configure --prefix=[absolute path to ~/local]
make
make install
要利用这种设置,您需要在相关的用户 rc 文件中设置相关的环境变量
export PATH=$HOME/local/bin:$PATH
export LIBRARY_PATH=$HOME/local/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$HOME/local/lib:$LD_LIBRARY_PATH
export C_INCLUDE_PATH=$HOME/local/include:$C_INCLUDE_PATH
要使用 ooc 中的库,约定是设置环境变量 OOC_LIBS。与上面讨论的本地设置保持一致,这可以是仅对该用户可见的路径
export OOC_LIBS=$HOME/local/ooc_libs
由于我们自己正在构建一个 ooc 库,因此文件层次结构属于 OOC_LIBS 内部。关于库结构和相关 use 文件的更多详细信息可以在 ooc 文档中找到。为了我们的目的,我们会有类似的东西
ooc-yaml yaml.use source YAML.ooc samples 01-test.occ
第一步是创建一个 use 文件,该文件描述了 ooc 库的布局以及编译到想要使用它的 ooc 程序所需的设置。一个基本的设置如下
Name: libYAML Version: 0.1.4 Description: Interface to libYAML Includes: yaml.h SourcePath: source
为了这次讨论的目的,我们将在上面文件层次结构的 source/YAML.ooc 内完成所有接口创建。因为我们希望这个文件包含我们上面建立的设置,所以我们在该文件的顶部包含以下行
use yaml
在该文件的顶部。
奇怪的是,libYAML 似乎没有定义任何常量!但以防您所连接的库确实包含常量,您的接口应该看起来像这样(上面以粗体显示的 C 代码,下面是 ooc)
#define A_FLOATING_POINT_CONSTANT 12.0 OOC_NAME_FOR_FLOATING_POINT_CONSTANT: extern( A_FLOATING_POINT_CONSTANT ) Float
#define A_STRING_CONSTANT "Twelve" OOC_NAME_FOR_STRING_CONSTANT: extern( A_STRING_CONSTANT ) CString
与 C 头文件连接意味着与 C 预处理器的许多奇怪部分以及开发人员用来跨平台和编程范式的技巧接触。libYAML 使用宏 YAML_DECLARE 来提供与 WIN32 的互操作性。为了我们的目的,我们将简单地扩展: #define YAML_DECLARE(type) type
这使得以下声明等效
YAML_DECLARE(const char *) yaml_get_version_string(void);
const char * yaml_get_version_string(void); YAMLGetVersionString: extern( yaml_get_version_string ) func() -> CString