1.前言
由于rust诞生时间太短,目前生态不够完善,因此大量的功能库都需要依赖于C、C++语言的历史积累。
而本文将要介绍的便是如何实现rust与c乃至c++之间实现互相调用。
2.动态库调用
首先最方便的还是动态库形式,大量的C语言代码库可以被编译为平台动态库、导出相应的函数,rust直接加载对应的动态库完成调用,这也是目前使用最广的方式。
比如rust中的windows、fltk-rs等等,由于它们之前已经用C语言实现了大量的代码、十几年、乃至几十年的积淀,短时间内难以用rust重写一遍。
所以为了能让rust可以使用它们,常常就是采用动态库调用的方式。
比如在windows系统上,一个最简单常用的winapi:MessagBoxW
,该函数用于弹出一个窗口。
此时如果我们想要在rust代码中调用这个函数(在没有官方提供的windows crate前提下),那么就可以先去官方文档看看它所在位置MessageBoxW:
可以看到,官方文档中注明了它在User32.dll
这个动态库中。
然后你可以下载everything等工具全局搜索这个动态库在哪里,找到它的路径(一般默认在C:\Windows\System32\user32.dll
),然后通过一些工具查看它的导出函数,就可以看到它。
比如我用vs本身提供的一个叫做dumpbin的工具,查看这个动态库的所有导出函数:
dumpbin /EXPORTS C:\Windows\System32\user32.dll
注意如果你想要执行这条命令,你需要进入vs自带的那个控制台中才能找到dumpbin这个命令。
然后搜索一下你就会发现它确实在这个动态库中:
然后我们就可以来到下一步,在rust中调用这个函数。
如果你对C++的Windows编程比较熟悉的话,就知道一般调用动态库有两种方式,一种是静态加载、一种是动态加载。
其中静态加载一般意味着你想要结合静态库一起使用,这样的加载方式意味着你的exe程序只有找到了这个动态库才能运行,如果找不到,那么就无法运行、并且会报错找不到相关的dll文件。
而动态加载意味着你可以让exe先跑起来、再去动态加载相关的dll文件,即使找不到、我们也可以主动抛出错误、或者寻找替代解决方案。
首先我们先来试试动态加载方案。
2.1 动态加载
动态加载动态库是一个平台通用的方案,仅仅只是底层调用的系统api不同而已,因此我们不需要再自己去rust中导出一遍各个平台的api用于打开动态库、转换相应的函数。