Mojo至少支持两种调用C函数的方法:
(有记录)external_call
。
external_call
将函数名称、返回类型和最多六个 (?) 参数类型作为参数,然后将相应的参数值作为输入。不过目前external_call
不支持指定函数库名,所以默认只能调用libc中的函数。稍后会详细介绍。
一个简单的external_call
看起来像这样:
let eightball = external_call["rand", Int32]()
print(eightball)
它将调用rand
C stdlib 中的函数,带有返回类型Int32
(第一个参数)并且没有函数参数。
有关更复杂的示例,请参阅call_div.mojo
此目录,它将两个参数传递给div
函数,并通过结构检索返回值。
(未记录?)声明一个函数指针类型,然后......调用它! Mojo 似乎至少使用平台 C 调用约定来进行简单的fn
别名声明。可以使用(未记录)加载此类函数指针sys.ffi.DLHandle
,然后调用。
请参阅call_atof_fptr.mojo
参考资料 中的完整示例,该示例演示了调用atof
以解析 C 字符串并从字符串返回双精度值。
(TODO:也可以通过嵌入式 MLIR 进行外部调用......)
非 libc 库中的函数
上面链接的示例使用 C 标准库中的函数,这些函数在 REPL 中隐式可用,或者通过 显式链接mojo build
。但是世界上还有许多其他我们可能想要调用的有用的 C 函数。以下是选项的概述。
从 REPL 调用共享库
(注意:在尝试下面的示例之前,请务必make
在此目录中运行;它们取决于 的存在libdemo.so
)
external_call
在 REPL 中使用仅要求函数名称可在过程映像中找到。sys.ffi.DLHandle("shared-lib.so")
将导致shared-lib.so
加载,并且可能dlopen
在引擎盖下使用。 (ctypes.CDLL
通过 Python 集成使用也可以)
然而,有一个非常大的警告:在包含 的单元被执行之前,对 的调用DLHandle
必须发生在单独的 REPL/笔记本单元中external_call
(出于与失败相同的原因mojo run
,下面将详细介绍)。
首先运行这个:
from sys import ffi
ffi.DLHandle("./libdemo.so")
然后这个:
var vec = DynamicVector[Float64]()
vec.push_back(1)
vec.push_back(2)
vec.push_back(30)
vec.push_back(51.112)
vec.push_back(40)
vec.push_back(51.0)
print(external_call["array_max", Float64, Pointer[Float64], Int64](vec.data, len(vec)))
程序应该打印51.112
.
mojo run
从(待定?)调用共享库
合乎逻辑的下一步是从上面的代码开始并main
在其周围添加一个块,然后使用 执行该函数mojo run
,或使用 进行编译mojo build
。
使用mojo run
,结果将如下所示(请参阅call_shared-bad.mojo):
JIT session error: Symbols not found: [ array_max ]
mojo: error: Failed to materialize symbols: { (exec, { main }) }
这会失败,因为 JIT 必须在编译阶段解析所有符号,而目前只有在执行函数array_max
后才可用。DLHandle
从 Mojo 编译的可执行文件调用库
mojo build
另一方面,使用 时,二进制文件无法链接:
call_shared-bad.mojo:(.text+0x104): undefined reference to `array_max'
collect2: error: ld returned 1 exit status
mojo: error: failed to link executable
mojo build
尚不支持链接器参数。然而,为了好玩,这个存储库包含帮助程序代码,scripts/
可以在其中挂钩编译过程并创建针对外部库静态链接的 Mojo 可执行文件。请参阅以下目录以获取更多信息:
从 Mojo 导出 C 可调用函数
Mojo 接受定义@export
上的注释fn
,该注释标记了 C 导出的以下函数(在更改日志中,否则未记录)。scripts/mojoc
还可以从 mojo 代码创建共享库。有关完整演示,请参阅以下内容: