crystal的c binding确实挺好用
如题,在下稍微使用了一下crystal的c binding功能,发现确实挺好用(要是lib声明可以根据头文件自动生成就更好了)
上一篇提到了因为会稍微用点儿图形的东西,所以没有在wsl安装crystal,这里说到的图形的东西就是本期要使用到的c库
以下均为在下根据官方的sdl binding例子自己踩坑,踩出来的
创建一个c binding很简单,只需要三步,显式链接这个库,编写外部函数,将这个库放进crystal的lib文件夹(这一步不能忘记,否则就会出链接问题,crystal不能直接去你的path里面找你的c库目录的)
首先是安装我们需要用的c库,这里在下选择raylib,一个算是比较经典的游戏工具库(这个库的安装在c库当中算是相当友好了,它甚至给你提供了一个使用zig为编译器的交叉编译方案,具体可以看src目录下的build.zig)
对于在下老Windows用户了(指在Windows下编程有些许年份了),vcpkg还是得有一个的,如果各位同样有vcpkg,那么只需要vcpkg install raylib:x64-windows(不喜欢64位的可以安装32位的,但可能会和crystal产生冲突,具体的在下没有试过不好断言),vcpkg本身是跨平台的,所以各平台应当是一样的
对于使用zig的,也可以用zig build xxx(编译方案名称,可以查看一下build.zig文件看看,在下相信安装了zig的应该都是会zig的,否则你安装它干什么对不对),记得把编译出来的库放到对应的位置就好
官方推荐的安装方式还有premake(一个由lua编写的c项目编译工具)
当然以上都是windows平台下的方式(为啥坚持使用Windows?因为穷咯,一台电脑工作和娱乐都是它,要知道在下于steam中点击linux支持以后可是库瞬间消失大半),如果你是linux或者macos那么应该系统自带的工具就能装,这里也就不多说了
我们的目标是让一个最基本的raylib项目可以跑起来,那么首先是我们预期的程序应当是这样的:
整个程序基本是将c/c++版本的翻译成了crystal,足够简单的同时也能基本上了解c binding的流程
那么,我们从链接并定义lib开始,以下代码我们这个程序所需要用到的所有东西的lib定义,由于我们本次只是演示,如果将整个库完整的binding写完再发出来,那么估计可能我就终于记起来b站密码了
首先是手动声明要链接的库,这里必须与你放入lib文件夹内的库文件xxx.lib中的xxx相同(在windows下是raylib.lib可不代表别的系统也为同名)
然后是lib block,内部需要将来自外部的函数和类型声明为crystal的,注意,这里不能使用基础类型以外的类型(因为那些是c没有的类型),可惜的是在下没有在官网找到类似cgo和rust ffi那样的与c的类型的对照表,但如果你使用了不允许的类型,编译时会报错,多逝几次就差不多都知道了
这里定义了一个Color的struct类型对应下面drawText需要使用的Color类型,注意,这里的struct和crystal的struct不同,是c的struct,而且需要与库内部的定义相符,这里原库的Color就是rgba,类型为unsigned char,也就是u8
然后是函数部分,这里也没有什么特别的,就是以fun关键字定义函数,后面为在c那一头的定义,类型应当与c那边的相符(这就是没有类型对照会很难受的主要原因)
可以看到我们这里并没有定义那个常量,因为这里的struct没办法以常规的方式(crystal的常规)使用,我们如果需要定义这个常量就需要封装一下,这里就来到了一个不强制要求的步骤了,那就是,在这个lib之上再封装一层
此时我们为color封装了一层,并在调用下层的时候为隐藏了转换类型的步骤
在windows下还需要记住一点,xxx.lib也是链接,你还得把raylib的动态库放在path或者当前项目的根目录下,别的平台应该简单不少
运行一下:

以上,crystal的c binding设计的确实挺合理清晰的,感兴趣的可以试试