首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我该如何在Vlang中创建静态库?

我该如何在Vlang中创建静态库?
EN

Stack Overflow用户
提问于 2021-10-13 10:39:29
回答 1查看 191关注 0票数 4

我对Vlang比较陌生,正在尝试创建一个静态库来尝试和测试它。我假设这只是在没有C的情况下编译成C,然后从这些C文件创建静态库,并从那里调用,但任何帮助都将不胜感激。谢谢。

EN

回答 1

Stack Overflow用户

发布于 2021-10-24 22:44:59

TL;DR:这种愚蠢而肮脏的方式。但我鼓励进一步阅读解释:

代码语言:javascript
复制
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内部的初始化不应该那么重要,然而,对于任何至少稍微复杂的东西,几乎所有的地狱都可以打破,所以对于只是玩自由实验,但如果它是为了生产,我宁愿不用2米长的杆子,直到有一个官方的方式或创建者同意这种方法。

Note2:因为它使用-shared开关,并且通常用于共享对象(动态库),所以应该没问题。但在C/C++世界中,这样的“应该”是相当危险的。:)

有了这些,我假设有一个非常简单的mylibrary.v文件。当前的方法可以使用module main或V的module <anything> + -shared开关。我正在使用后者。

将有一个私有fn函数和一个公共pub fn函数:

代码语言:javascript
复制
module notmain

fn say_hi() {
    println("Hi!")
}

pub fn say_hello() {
    println("Hello!")
}

现在为了构建,让我们从简单的C代码转换开始:

代码语言:javascript
复制
v -shared -o mylibrary.c mylibrary.v

这个文件通常用于创建一个mylibrary.so文件,并包含我们的函数的引用。

现在让我们组装一个头部。V发出的C有一个模块名的前缀,这将成为grep的一个很好的模式。如果你使用常量,可变变量,等等,你需要更多地检查这到底是如何影响最终的二进制文件的。我将假设您不想使用库中的全局变量来使事情变得更简单(尽管“应该”仍然可以工作,但如果发出的C是可以的话)。

代码语言:javascript
复制
grep notmain mylibrary.c

我得到了类似这样的东西:

代码语言:javascript
复制
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 fnfn。我将仅从公共函数组装一个头文件:

代码语言:javascript
复制
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创建一个静态库

代码语言:javascript
复制
gcc -c mylibrary.c -o mylibrary.o
ar rcs mylibrary.a mylibrary.o

并通过一个示例main.c文件运行它:

代码语言:javascript
复制
#include "mylibrary.h"
int main(void) {
    notmain__say_hi();
    notmain__say_hello();
    return 0;
}

你可以用两种(或更多)的方式编译它:

代码语言:javascript
复制
gcc -o main main.c mylibrary.a
gcc -o main main.c -L. -l:mylibrary.a

如果将库命名为lib<something>.a,则可以使用-l<something>标志。:正在指定文件名。

GCC显然会讲述隐式声明,因为声明不在头部中,也不在其他任何地方,您仍然会看到它在运行时(here's why)工作。

让我们让它变得更易用(用rm *.a *.c *.h *.o main_*清理):

build.sh

代码语言:javascript
复制
#!/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

和日志:

代码语言:javascript
复制
# ./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!

玩得开心!^^

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69554012

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档