developer.gnome.org/gobject/2.6…
导出C API C API由通常从二进制文件导出的一组函数和全局变量定义。C函数具有任意数量的参数和一个返回值。因此,每个函数都由函数名称和描述函数参数和返回值的C类型集唯一标识。同样,API导出的全局变量由它们的名称和类型来标识。
因此,AC API仅由一组名称与一组类型相关联来定义。如果您知道函数调用约定以及C类型到所使用平台所使用的计算机类型的映射,则可以解析每个函数的名称以查找与此函数关联的代码在内存中的位置,然后为该函数构造一个有效的参数列表。最后,您要做的就是使用参数列表触发对目标C函数的调用。
为了便于讨论,下面是一个示例C函数以及由Linux计算机上的GCC生成的相关的32位x86汇编代码:
static void
function_foo (int foo)
{
}
int
main (int argc,
char *argv[])
{
function_foo (10);
return 0;
}
push $0xa
call 0x80482f4 <function_foo>
上面显示的汇编代码非常简单:第一个指令将十六进制值0xa(十进制值10)作为32位整数压入堆栈并调用 function_foo。如您所见,C函数调用由GCC作为本机函数调用实现(这可能是最快的实现)。
现在,假设我们function_foo要从Python程序调用C函数。为此,Python解释器需要:
查找功能所在的位置。这可能意味着找到由导出该函数的C编译器生成的二进制文件。
将功能代码加载到可执行存储器中。
在调用函数之前,将Python参数转换为C兼容参数。
使用正确的调用约定来调用函数。
将C函数的返回值转换为与Python兼容的变量,以将其返回给Python代码。
上面描述的过程非常复杂,并且有很多方法可以使它对C和Python程序员完全自动化和透明:
第一个解决方案是用手编写大量粘合代码,每个导出或导入的函数一次,它们执行Python到C的参数转换和C到Python的返回值转换。然后,此粘合代码与解释器链接,该解释器允许Python程序调用将工作委托给C函数的Python函数。
另一个更好的解决方案是,使用特殊的编译器自动读取输出的原始函数签名,为导出或导入的每个函数自动生成粘合代码。
GLib使用的解决方案是使用GType库,该库在运行时保存由程序员操作的所有对象的描述。 然后,特殊的通用粘合代码使用此所谓的动态类型 [1]库在不同的运行时域之间自动转换函数参数和函数调用约定。
GType实现的解决方案的最大优点是,位于运行时域边界的粘合代码只需编写一次:下图对此进行了更清晰的说明。
当前,至少存在Python和Perl通用胶合代码,这使得使用GType直接在Python或Perl中编写的C对象成为可能,而所需的工作量却很少:无需自动或大量生成大量胶合代码用手。
尽管可以说该目标值得称赞,但它的追求对整个GType / GObject库产生了重大影响。如果C程序员忘记了GType / GObject库不仅旨在为C程序员提供类似OO的功能,而且还提供透明的跨语言互操作性,则可能会对接下来几章中介绍的功能的复杂性感到困惑。