没有包装类型,是否可以从OCaml调用C函数? [英] Is it possible to call into C functions from OCaml, without wrapped types?

查看:73
本文介绍了没有包装类型,是否可以从OCaml调用C函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在OCaml中编写一个(非常微小,简单的-我不知道我在做什么,让我们成为现实!)编译器.

I'm trying to write a (desperately tiny, simple — I have no idea what I'm doing, let's be real!) compiler in OCaml.

我真的很想避免将任何 ISO-C代码检入到项目中(尽管相当了解C;这里的目标是专门学习和使用OCaml.)需要在OCaml中为编译后的语言编写一个运行时",将其与主项目分开编译,然后将其与编译器本身的输出链接.

I'd really like to avoid checking any ISO-C code into the project (despite knowing C fairly well; the goal here is to learn and use OCaml exclusively.) Pursuant to this, I need to write a "runtime" for the compiled language in OCaml, compile it separately from the primary project, and then link it against the compiler-itself's output.

不幸的是,它看起来像 any 外部函数-甚至那些不涉及任何OCaml数据结构/OCaml堆的外部函数,都应该使用OCaml的C宏来构建:

Unfortunately, it looks like any external functions — even ones that don't touch any OCaml data-structures / the OCaml heap, are expected to be constructed using OCaml's C macros:

CAMLprim value scheme_entry(value unit) {
    int i;
    i = 42;
    return Val_int(i);
}

如果我自己发出汇编说明,则这可能不是一个选择. (至少直到我学到更多为止!)

This probably isn't an option, if I'm emitting the assembly instructions myself. (At least, not until I learn quite a bit more!)

有没有任何方法(包括hacky的方法,这是一个个人学习项目)来调用极其简单的功能,例如来自OCaml的以下功能?

Is there any way (including hacky ones — this is a personal learning project) to invoke extremely simple functions like the following from OCaml?

_scheme_entry:
    movl $42 %eax
    ret

作为参考,我正在研究Ghuloum的IACC: http://ell.io/tt$ocameel

推荐答案

不幸的是,它看起来像任何外部函数-甚至那些不涉及任何OCaml数据结构/OCaml堆的函数,都应该使用OCaml的C宏来构建:

Unfortunately, it looks like any external functions — even ones that don't touch any OCaml data-structures / the OCaml heap, are expected to be constructed using OCaml's C macros:

不,不是.如果您的函数根本没有碰到OCaml,或者没有分配或不使用分配的值,那么您可以直接调用函数,例如

No, they are not. If your function doesn't touch OCaml at all, or doesn't allocated or works with the allocated values, then you can call functions directly, e.g.,

value scheme_entry(value unit) {
    int i;
    i = 42;
    return Val_int(i);
}

在OCaml方面:

external scheme_entry : unit -> int = "scheme_entry" [@@noalloc]

在OCaml的最新版本中,我们获得了更大的控制权,因此我们可以传递浮点数和更大的整数而无需装箱/拆箱.在此处中阅读进一步的信息.

In the latest releases of OCaml we got even more control, so that we can pass floats and bigger integers without boxing/unboxing. Read here for the further info.

请注意,Val_int只是将C整数左移一位并将最低有效位设置为1的宏,即.因此,如果您不需要将OCaml整数转换为C整数,反之亦然,那么您甚至不需要使用此宏,因此您的运行时可能完全不知道OCaml,例如:

Note, that Val_int is just a macro that shift a C integer one bit to the left and sets the least significant bit to one, i.e., (((unsigned)(x) << 1)) + 1). So, if you don't need to translate OCaml integers to C integers and vice verse, then you don't even need to use this macros, so you runtime can be totally unaware of OCaml, for example:

 void runtime_init(void) {
    printf("Hello from runtime");
 }

在OCaml方面:

 val runtime_init : unit -> unit = "runtime_init" [@@noalloc]

注意:[@@noalloc]属性是在OCaml 4.03中添加的,在该版本之前,您应该使用"noalloc",例如

Note: the [@@noalloc] attribute was added in OCaml 4.03, before that version, you should use "noalloc", e.g.,

 val runtime_init : unit -> unit = "runtime_init" "noalloc"

当然,您非常简单的函数应遵循适合您特定体系结构和操作系统的C调用约定.因此,如果您的函数破坏了一些应该保留的寄存器,那么您会遇到麻烦,例如,在amd64 ABI上,您应该保留rbp,rbx,r12-r15.没有什么OCaml特定于此要求,只是普通的C调用约定.

Of course, your extremely simple function should obey the C calling convention that is appropriate to your particular architecture and operating system. So if your function destroys some registers that should be preserved, you should expect troubles, for example on amd64 ABI you should preserve rbp, rbx, r12-r15. There is nothing OCaml specific with this requirement, just a normal C calling convention.

这篇关于没有包装类型,是否可以从OCaml调用C函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆