是否存在以不同方式传递int8_t、int16_t和int32_t的32位或64位平台?
我之所以这样问,是因为OCaml (尚未发布的4.03+)可以直接将32位或64位整数和双精度数传递给C,但不能传递8位或16位整数或单精度浮点数。
编辑:基本上我是在问
char x(char y)
可以被调用为
int x(int y)
发布于 2016-04-03 13:40:23
在调用约定中的关键字是约定,并且约定因许多原因而不同,例如体系结构等。我可能正在使用int8_t,但在幕后它可能会占用32位的空间,或者在64位系统上占用64位。只要它的行为像int8_t一样,我就不在乎。一种语言可能会公开一个char,但它可能会被表示为一个int,C可以做到这一点。当您在比C更高的抽象层次上深入研究语言的C接口时,您会开始看到编译器编写者为了简化他们的生活而做出的一些设计决策。
发布于 2016-04-03 13:52:56
即使存在以不同方式传递int8_t、int16_t和int32_t的32位或64位平台(出于各种原因,我怀疑是否存在),这也不能成为OCaml不能传递这些参数的借口。它所要做的就是遵循平台的标准ABI,世界就会变得很好。很可能,FFI根本不会实现它,因为它对实现者来说用处不够大。
这就是说,你不太可能找到这样的平台的一个主要原因是,大多数C编译器试图保持与K&R C的一些兼容性,至少是标记兼容性,其中不需要声明函数原型;未声明的函数将被调用,就像它们具有int参数和返回值一样。由于这样的原因,几乎所有的ABI总是将所有整数参数提升为原生字长,以便它们将与实际使用的任何具体整数类型保持赋值兼容,即使使用更小的单位可以更有效地传递参数。
EDIT:来回答您编辑过的问题,然后在所有标准的int x(int)上,是的,您可以将ABI作为ABI调用。但是,需要注意的是,编译器可能会假定传递的字的高位为零,因此,如果您将512作为参数传递给C函数中用作char的参数,则可能会得到未定义的行为。
发布于 2016-04-04 00:32:04
是否存在以不同方式传递int8_t、int16_t和int32_t的32位或64位平台?
大概确实存在一个,可能是实验性的,也可能是历史性的。但是,如果我们将讨论范围限制在OCaml系统(主要实现)支持的体系结构集上,那么答案是否定的。
我之所以这样问,是因为OCaml (尚未发布的4.03+)可以直接将32位或64位整数和双精度数传递给C,但不能传递8位或16位整数或单精度浮点数。
原因是因为OCaml对整数有不同的表示。与C表示相比,它向左移位一位并递增。因此,0表示为C的1,1表示为3,依此类推。最低有效位用于区分立即值和指针。因此OCaml整数实际上少了一位,即在64位系统上为63位,在32位系统上为31位。这意味着,在将一个整数传递给c函数之前,您需要将它向右移位。简单且低成本的操作。char类型也由int表示,所以它也有同样的问题。在标准库中没有int8_t和int16_t,所以我不能谈论它们。第三方库可以在任何表示中引入它们,这些表示可能支持也可能不支持直接传递到C函数。
OCaml的int32、int64、nativeint和float都表示为盒值,即它们在OCaml的堆中分配,并作为指针传递给OCaml函数。分配的块的表示与C中的相同,因此允许按原样传递它。当然,只有当被调用的函数不将该值存储在某个地方并且不调用任何可能引发垃圾回收的函数时,这才是安全的。在4.03之前,程序员被要求对值进行拆箱,方法是将内容复制到C变量中(安全的方式),或者取消引用并直接传递它(一种危险的方式-您应该知道自己在做什么)。版本4.03提供了一个新的注释(属性unboxed),它是以前存在的"%float"注释的泛化。此注释允许直接传递此特定四种类型的值。此注释适用于一组有限的函数类型,当然,它只对特定函数是安全的。
所以,总而言之,小整数以一种非常快的方式传递给C。装箱的值通常需要一些额外的工作,这也引入了对垃圾收集和分配的调用。为了缓解这个问题,4.03添加了一些优化,允许在安全的情况下直接传递它们。
编辑:基本上我想问的是
char x(char y)
可以被调用为
int x(int y)
从OCaml对外函数接口的角度来看,这并没有太大的区别。唯一的问题是,OCaml int比C int小,所以如果x可能返回一个不适合OCaml表示的值,则应该使用更大(并装箱)的类型,例如nativeint。在许多情况下,这个问题可以忽略,例如,当int是一个错误代码时,或者已知它很小,或者不大于输入参数。
https://stackoverflow.com/questions/36381627
复制相似问题