vlang - 我将如何在 Vlang 中创建静态库?
问题描述
我对 Vlang 比较陌生,并且正在尝试创建一个静态库来尝试对其进行测试。我认为它只涉及编译到 C 而不从这些 C 文件创建静态库,然后从那里调用,但任何帮助将不胜感激。谢谢你。
解决方案
TL;DR:愚蠢而肮脏的方式。但我鼓励进一步阅读解释:
v -shared -o mylibrary.c mylibrary.v
gcc -c mylibrary.c -o mylibrary.o
ar rcs mylibrary.a mylibrary.o
gcc -o main main.c mylibrary.a
./main
没有正式的方式(或者至少没有weekly.2021.42.1
),但是@AlexanderBielby 提到了一种非正式的方式。这里是:
注意:对于简单的东西,V 内部的初始化应该没那么重要,但是,对于任何至少稍微复杂一点的东西,几乎所有的地狱都可以打破,所以对于只是玩随意尝试,但如果它是为了生产,我宁愿不要用 2m 的杆子碰它,直到有官方的方式或创作者对这种方法没问题。
注意2:由于它使用-shared
switch并且它通常用于共享对象(动态库),它应该没问题。但是这样的“应该”在 C/C++ 世界中是相当危险的。:)
有了这个,我假设一个非常简单的mylibrary.v
文件。当前的方式可以使用module main
或使用V 的module <anything>
+-shared
开关。我使用的是后者。
将有一个私有fn
函数和一个公共pub fn
函数:
module notmain
fn say_hi() {
println("Hi!")
}
pub fn say_hello() {
println("Hello!")
}
现在构建让我们从简单的 C 语言转换开始:
v -shared -o mylibrary.c mylibrary.v
该文件通常用于创建mylibrary.so
文件并包含我们函数的引用。
现在让我们组装一个标题。V 发出的 C 具有模块名称的前缀,这将作为grep
. 如果你使用常量、可变变量等,你需要更多地检查它对最终二进制文件的影响。我假设您不想使用库中的全局变量来简化事情(尽管如果发出的 C 没问题,“应该”仍然可以工作)。
grep notmain mylibrary.c
我得到了这样的东西:
VV_LOCAL_SYMBOL void notmain__say_hi();
void notmain__say_hello();
VV_LOCAL_SYMBOL void notmain__say_hi(void) {
void notmain__say_hello(void) {
// Initializations for module notmain :
这意味着发出的 C 区分pub fn
和fn
。我将仅从公共函数中组装一个标头:
cat <<EOF > mylibrary.h
#pragma once
#ifndef MYLIBRARY_H
#define MYLIBRARY_H
EOF
for func in $(grep "pub fn" $1|cut -f 3 -d " "|sed -e "s/()//")
do
grep notmain__${func} mylibrary.c|grep ';' >> mylibrary.h
done
echo '#endif' >> mylibrary.h
然后只需编译它并创建一个静态库ar
:
gcc -c mylibrary.c -o mylibrary.o
ar rcs mylibrary.a mylibrary.o
并通过示例main.c
文件运行它:
#include "mylibrary.h"
int main(void) {
notmain__say_hi();
notmain__say_hello();
return 0;
}
您可以通过两种(或更多)方式编译它:
gcc -o main main.c mylibrary.a
gcc -o main main.c -L. -l:mylibrary.a
如果您命名 library lib<something>.a
,那么您可以使用-l<something>
flag 代替。:
正在指定文件名。
GCC 显然会告诉隐式声明,因为该声明不存在于标头中或其他任何地方,您仍然会看到它在运行时工作(这就是原因)。
让我们让它更有用一点(用 清洁rm *.a *.c *.h *.o main_*
):
构建.sh:
#!/bin/sh -ex
# use CC, AR and V env vars to set custom paths
if [ -z "$1" ]
then
echo 'V=<path to V binary> ./build.sh <name>.v'
exit 1
fi
NAME=$(echo $1|sed -e 's/\.v//')
MOD=$(grep 'module ' $1|cut -f 2 -d' ')
FUNCS=$(grep "pub fn" $1|cut -f 3 -d " "|sed -e "s/()//")
GUARD=$(echo ${NAME}_H|tr '[:lower:]' '[:upper:]')
V=${V:-./v}
CC=${CC:-gcc}
AR=${AR:-ar}
transpile() {
${V} -shared -o ${NAME}.c ${NAME}.v
}
headerify() {
cat <<EOF > ${NAME}.h
#pragma once
#ifndef ${GUARD}
#define ${GUARD}
EOF
for func in ${FUNCS}
do
grep ${MOD}__${func} ${NAME}.c|grep ';' >> ${NAME}.h
done
echo '#endif' >> ${NAME}.h
}
static_compile() {
${CC} -c ${NAME}.c -o ${NAME}.o
}
archive() {
${AR} rcs ${NAME}.a ${NAME}.o
}
create_main() {
cat <<EOF > main.c
#include "${NAME}.h"
int main(void) {${MOD}__say_hi();${MOD}__say_hello();return 0;}
EOF
}
compile_direct() {
${CC} -o main_direct main.c ${NAME}.a
}
compile_link() {
${CC} -o main_link main.c -L. -l:mylibrary.a
}
run() {
./main_direct
./main_link
}
transpile
headerify
static_compile
archive
create_main
compile_direct
compile_link
run
和日志:
# ./build.sh mylibrary.v
+ [ -z mylibrary.v ]
+ echo mylibrary.v
+ sed -e s/\.v//
+ NAME=mylibrary
+ grep module mylibrary.v
+ cut -f 2 -d
+ MOD=notmain
+ grep pub fn+ cut -f 3 -d
mylibrary.v
+ sed -e s/()//
+ FUNCS=say_hello
+ tr+ [:lower:] [:upper:]
echo mylibrary_H
+ GUARD=MYLIBRARY_H
+ V=./v
+ CC=gcc
+ AR=ar
+ transpile
+ ./v -shared -o mylibrary.c mylibrary.v
+ headerify
+ cat
+ + grep notmain__say_hello mylibrary.c
grep ;
+ echo #endif
+ static_compile
+ gcc -c mylibrary.c -o mylibrary.o
+ archive
+ ar rcs mylibrary.a mylibrary.o
+ create_main
+ cat
+ compile_direct
+ gcc -o main_direct main.c mylibrary.a
main.c: In function ‘main’:
main.c:2:17: warning: implicit declaration of function ‘notmain__say_hi’; did you mean ‘notmain__say_hello’? [-Wimplicit-function-declaration]
2 | int main(void) {notmain__say_hi();notmain__say_hello();return 0;}
| ^~~~~~~~~~~~~~~
| notmain__say_hello
+ compile_link
+ gcc -o main_link main.c -L. -l:mylibrary.a
main.c: In function ‘main’:
main.c:2:17: warning: implicit declaration of function ‘notmain__say_hi’; did you mean ‘notmain__say_hello’? [-Wimplicit-function-declaration]
2 | int main(void) {notmain__say_hi();notmain__say_hello();return 0;}
| ^~~~~~~~~~~~~~~
| notmain__say_hello
+ run
+ ./main_direct
Hi!
Hello!
+ ./main_link
Hi!
Hello!
玩得开心!^^
推荐阅读
- javascript - 如何比较 2 个对象数组并在 Javascript 中返回单个数组结果?
- javascript - 如何理解“这样的绑定只定义一次,永不改变”这句话?
- python - Pandas:对列的子集应用过滤器
- php - 如何缩小或提高 laravel 8 刀片模板的速度?
- javascript - Vuejs - 焦点元素检查
- android - 如何从sqlite数据库中的日期数据中提取日期和月份
- leaflet - 我的第一个实验用地图、点和数学表达式学习 R 闪亮
- node.js - 使用 multer 将多个图像上传到 AWS S3
- download - 如何下载 HLS(HTTP Live Streaming)?
- rust - rltk vga 字体显示不正确