集成C代码库

优势

V的代码库很多都直接调用C标准库函数来实现,对C标准库的依赖还是很重的

由于V代码编译后生成的是C代码,然后再调用C编译器编译成可执行文件

这样的机制决定了V语言可以很方便地调用C世界的各种代码库

这对于V语言来说,是个很大的一个优势,毕竟C代码库经过多年的积累,很丰富

如何调用

在V代码里调用C代码也非常简单,在V标准库里随处可见

以下是调用C代码库的基本步骤:

定义#flag

定义flag这一步是可选的,比如调用C标准库的函数就不需要

一般调用第三方库才需要用到,如果有需要,flag的定义要放在C语言宏之前

关于#flag详细内容,参考下面的flag段落

在V代码中使用C语言宏

比如#include宏或#define宏,编译时这些宏会被原封不动地搬到生成的C代码中

然后用V的语法定义要使用的C函数或C结构体的声明

函数名或结构体名一定要在C名称的基础上添加C.前缀

然后就可以在V代码中使用C函数或结构体

调用的时候,名称前可以使用C.作为前缀,也可以不使用,不过还是建议统一使用C.前缀,代码更容易区分是调用C函数或C结构体.

其实V编译的时候,会统一把函数和结构体名称前面的C.统一去掉,这样在C代码里面就可以正常调用了

调用标准库的例子:

module main

#include //使用C语言宏,包含头文件

fn C.getpid() int //定义要使用的C函数声明,名字在C函数名字前统一加上C.前缀

fn main(){

pid:=C.getpid()

pid2:=getpid() //C.前缀去掉也可以

println(pid)

println(pid2)

}

myslq库中的参考代码:

//宏

#flag -lmysqlclient

#flag linux -I/usr/include/mysql

#include

//声明要使用的C结构体

struct C.MYSQL

struct C.MYSQL_RES

//声明要使用的C函数

fn C.mysql_init(mysql &C.MYSQL) &C.MYSQL

fn C.mysql_real_connect(mysql &C.MYSQL, host byteptr, user byteptr, passwd byteptr, db byteptr, port u32, unix_socket byteptr, clientflag u64) &C.MYSQL

fn C.mysql_query(mysql &C.MYSQL, q byteptr) int

fn C.mysql_select_db(mysql &C.MYSQL, db byteptr) int

fn C.mysql_error(mysql &C.MYSQL) byteptr

fn C.mysql_errno(mysql &C.MYSQL) int

fn C.mysql_num_fields(res &C.MYSQL_RES) int

fn C.mysql_store_result(mysql &C.MYSQL) &C.MYSQL_RES

fn C.mysql_fetch_row(res &C.MYSQL_RES) &byteptr

fn C.mysql_free_result(res &C.MYSQL_RES)

fn C.mysql_real_escape_string_quote(mysql &C.MYSQL, to byteptr, from byteptr, len u64, quote byte) u64

fn C.mysql_close(sock &C.MYSQL)

//调用C函数或结构体

pub fn connect(server, user, passwd, dbname string) ?DB {

conn := C.mysql_init(0)

if isnil(conn) {

return error_with_code(get_error_msg(conn), get_errno(conn))

}

conn2 := C.mysql_real_connect(conn, server.str, user.str, passwd.str, dbname.str, 0, 0, 0)

if isnil(conn2) {

return error_with_code(get_error_msg(conn), get_errno(conn))

}

return DB {conn: conn2}

}

另一个集成C代码库的例子:vlib/clipboard/clipboard_linux.c.v

使用了结构体标注[typedef]来定义C语言的结构体

//定义C宏

#flag -lX11

#include

//定义C结构体

[typedef]

struct C.Display //在v代码中只需使用C结构体,不使用结构体字段

[typedef]

struct C.XSelectionRequestEvent{ //在v代码中要使用结构体字段,要定义所需的字段

mut:

display &C.Display /* Display the event was read from */

owner C.Window

requestor C.Window

selection C.Atom

target C.Atom

property C.Atom

time int

}

//定义C函数

fn C.XInitThreads() int

fn C.XCloseDisplay(d &Display)

fn C.XFlush(d &Display)

fn C.XDestroyWindow(d &Display, w C.Window)

简单封装

其实,直接在V代码中使用C函数或者结构体也是可以的,不过,由于命名方式不一致的原因,习惯上也可以对C函数或结构体,进行一层简单封装,名字可以重新改为V风格,或者更为简短的名字

一般来说,对一个C代码库中的简单封装会涉及到:结构体,函数,枚举这3大类

如果是小的C代码库,可以直接把这3类的简单封装都放在一个V源文件中

如果C代码库规模大一些,也可以这3类,各自单独一个V源文件,归属于同一个V模块

以下代码是GUI代码库中引用了sokol C代码库后,进行的简单封装:

vlib/sokol/sokol.v部分代码:

//只要在同模块中的任何一个V源文件中引入,该模块的其他源文件就可以直接使用C代码库内容

#define SOKOL_IMPL

#define SOKOL_NO_ENTRY

#include "sokol_app.h"

#define SOKOL_IMPL

#define SOKOL_NO_DEPRECATED

#include "sokol_gfx.h"

//可以直接使用,函数以C.作为前缀

pub fn init_sokol() {

C.sapp_isvalid()

C.sapp_width()

}

//也可以进行简单的封装

module sapp

[inline] //可以给函数添加inline标注,变为内联函数

pub fn isvalid() bool {

return C.sapp_isvalid()

}

[inline]

pub fn width() int {

return C.sapp_width()

}

函数的[inline]标注

对C函数进行简单的封装时,可以给函数添加inline标注,编译生成C代码时,这个函数就会变成C语言里的static inline函数

内联函数有些类似于宏,内联函数的代码会被直接嵌入在它被调用的地方,调用几次就嵌入几次,没有使用call指令。这样省去了函数调用时的一些额外开销,不过调用次数多的话,会使可执行文件变大,这样会降低整个程序的运行速度

像上面那个简单的封装,函数只有1行代码,嵌入到被调用的地方也还是1还代码,既能省去函数调用时的额外开销,提升性能,又不会使可执行文件变大

同时也可以统一和简化C函数的命名,变为V风格的简短命名,一举多得

[inline]

pub fn width() int {

return C.sapp_width()

}

结构体简单封装

定义C结构体等价的V版本结构体,V版本结构体名称以C.做前缀

这样就可以直接使用V版本的结构体来创建变量

用V版本的结构体创建变量,编译生成的C代码中,就是用C版本结构体创建了变量

C代码库中的结构体:

typedef struct sapp_event {

uint64_t frame_count;

sapp_event_type type;

sapp_keycode key_code;

uint32_t char_code;

bool key_repeat;

uint32_t modifiers;

sapp_mousebutton mouse_button;

float mouse_x;

float mouse_y;

float scroll_x;

float scroll_y;

int num_touches;

sapp_touchpoint touches[SAPP_MAX_TOUCHPOINTS];

int window_width;

int window_height;

int framebuffer_width;

int framebuffer_height;

} sapp_event;

定义等价的V版本结构体:字段数量一样,字段名称一样,字段类型一样

如果字段类型是枚举的,也可以再定义等价的V版本枚举

pub struct C.sapp_event {

pub:

frame_count u64

@type EventType //这个type字段有点特殊,因为是V的关键字,要用@开头才可以

key_code KeyCode //枚举类型

char_code u32

key_repeat bool

modifiers u32

mouse_button MouseButton //枚举类型,下面有MouseButton的V版本定义

mouse_x f32

mouse_y f32

scroll_x f32

scroll_y f32

num_touches int

touches [8]sapp_touchpoint //数组类型

window_width int

window_height int

framebuffer_width int

framebuffer_height int

}

枚举简单封装

其实就是定义一个跟C版本枚举一样的枚举,枚举名和枚举值一样

pub enum MouseButton {

invalid = -1

left = 0

right = 1

middle = 2

}

关于#flag标记

这个#flag标记跟v编译器的-cflags选项的用法是一样的,用于传递额外的flag参数给C编译器

要在使用C宏之前先定义#flag

-l 表示在库文件的搜索路径列表中添加指定的路径

-I 表示在头文件的搜索路径中添加指定的路径

-D 表示设置编译时变量

还可以在#flag后增加平台标识,针对不同的平台配置不同的flag,目前支持的平台有:linux,darwin,windows

以下例子,提供参考:

//#flag文档里面的:

#flag linux -lsdl2

#flag linux -Ivig

#flag linux -DCIMGUI_DEFINE_ENUMS_AND_STRUCTS=1

#flag linux -DIMGUI_DISABLE_OBSOLETE_FUNCTIONS=1

#flag linux -DIMGUI_IMPL_API=

//mysql包里面的:

#flag -lmysqlclient //-l开头,表示在库文件的搜索路径中添加mysqlclient

#flag linux -I /usr/include/mysql //-I开头,在头文件的搜索路径中添加指定的路径, 针对linux平台,这样才可以搜索到下面的mysql.h头文件

#include

//sokol包里面的:

#flag -I @VROOT/thirdparty/sokol //@VROOT指向v编译器的根路径

#flag -I @VROOT/thirdparty/sokol/util

#flag darwin -fobjc-arc //针对mac平台,提供额外的flag参数:-fobjc-arc

#flag linux -lX11 -lGL //针对linux平台,提供额外的flag参数

#flag windows -lgdi32 //针对window平台,提供额外的flag参数:-l开头,表示链接gdi32

// OPENGL

#flag -DSOKOL_GLCORE33 //提供额外的flag参数:-DSOKOL_GLCORE33

#flag darwin -framework OpenGL -framework Cocoa -framework QuartzCore

c v语言 小数后20位,V语言学习笔记-30集成C代码库相关推荐

  1. 习题:编程求圆周长、圆面积、圆球体积、设圆半径r=1.5。要求:用scanf输入数据,输出计算结果,输出时要求有文字说明,取小数后2位...

    1 /*编程求圆周长.圆面积.圆球体积.设圆半径r=1.5.要求:用scanf输入数据,输出计算结果,输出时要求有文字说明,取小数后2位*/ 2 /*圆球体积公式 V=(4*π*r3)/3 */ 3 ...

  2. python读数据小数点_将excel数据读入pandas dataframe,精确到小数点后20位

    我试着用excel读取数据pandas.excel文件()到数据帧中,然后使用tocsv输出文本文件.在 此输出文本文件的精度应为小数点后20位,并四舍五入到小数点后20位.在 如果excel中的输入 ...

  3. 前端处理运算 向上取整 向下取整 四舍五入 四舍五入(自定义取小数后几位)

    向上取整 Math.ceil() 向下取整 Math.floor() 四舍五入 Math.round() 四舍五入(自定义取小数后几位) // 计算结果是字符串 (5.6666666).toFixed ...

  4. HALCON 20.11:深度学习笔记(5)---设置超参数

    HALCON 20.11:深度学习笔记(5)---设置超参数 HALCON 20.11.0.0中,实现了深度学习方法.关于超参数的有关设置内容如下: 不同的DL方法被设计用于不同的任务,它们的构建方式 ...

  5. HALCON 20.11:深度学习笔记(12)---语义分割

    HALCON 20.11:深度学习笔记(12)--- 语义分割 HALCON 20.11.0.0中,实现了深度学习方法. 本章解释了如何使用基于深度学习的语义分割,包括训练和推理阶段. 通过语义分割, ...

  6. HALCON 20.11:深度学习笔记(11)---目标检测

    HALCON 20.11:深度学习笔记(11)---目标检测 HALCON 20.11.0.0中,实现了深度学习方法. 本章讲解了如何使用基于深度学习的对象检测. 通过对象检测,我们希望在图像中找到不 ...

  7. HALCON 20.11:深度学习笔记(9)---异常检测

    HALCON 20.11:深度学习笔记(9)---异常检测 HALCON 20.11.0.0中,实现了深度学习方法. 本章解释了如何使用基于深度学习的异常检测. 通过异常检测,我们想要检测图像是否包含 ...

  8. HALCON 20.11:深度学习笔记(10)---分类

    HALCON 20.11:深度学习笔记(10)---分类 HALCON 20.11.0.0中,实现了深度学习方法. 本章解释了如何在训练和推理阶段使用基于深度学习的分类. 基于深度学习的分类是一种对一 ...

  9. HALCON 20.11:深度学习笔记(7)---术语表

    HALCON 20.11:深度学习笔记(7)---术语表 HALCON 20.11.0.0中,实现了深度学习方法.下面,我们将描述深度学习环境中使用的最重要的术语: anchor (锚) Anchor ...

最新文章

  1. 华为云服务器linux切换账号,华为云Windows服务器如何切换为Linux系统?
  2. mysql倍增表的内容,mysql - DATEDIFF不会在触发器内倍增 - SO中文参考 - www.soinside.com...
  3. 黄聪:Microsoft Enterprise Library 5.0 系列教程(四) Logging Application Block
  4. Keepalived 做负载均衡(简单实例)
  5. 【内网渗透】找到内网关键节点
  6. gmat阅读.html,GMAT阅读方法之——抽象词提炼
  7. Q107:Linux系统下GDB对PBRT-V3进行debug
  8. 百度文库免点券下载方法
  9. 机器学习中的训练集、验证集、测试集;交叉验证方法
  10. adb 切换usb模式_如何用adb打开usb调试
  11. 2021年茶艺师(中级)考试内容及茶艺师(中级)操作证考试
  12. 6.torchvision
  13. 【大学生数学建模竞赛时间一览表】
  14. 案例:js实现关闭淘宝二维码
  15. 使用RENREN-GENERATOR时遇到循环错误问题 Relying upon circular references is discouraged and they are prohibited
  16. JavaSE--IO流
  17. 哈工大机器学习复习笔记(四)
  18. 人事部门HR办公流程自动化-人事部门RPA机器人流程自动化解决方案
  19. Linux C语言编写2048小游戏
  20. web总结及网页制作

热门文章

  1. JAVA 的性能优化
  2. 严版数据结构(第一章)
  3. 图象恢复——(逆滤波,维纳滤波)
  4. Python基于basemap画论文级别的多子图空间场
  5. 使用JSON-Schema验证数据,第1部分
  6. 在win10上安装oracle10g
  7. 自由 Freedom
  8. B端产品客户画像的一点感悟
  9. 如何培养自己的编程兴趣
  10. halcon循环语句,条件句结构格式