符合中小企业对网站设计、功能常规化式的企业展示型网站建设
本套餐主要针对企业品牌型网站、中高端设计、前端互动体验...
商城网站建设因基本功能的需求不同费用上面也有很大的差别...
手机微信网站开发、微信官网、微信商城网站...
golangc++openfopen区别是来源不同,golangc是ANSIC标准中的C语言库函数,在不同的系统中应该调不同的内核api,返回的是一个指向文件结构的指针。openfopen是unix系统调用函数(包括Linux),返回的是文件描述符,它是文件描述符表里的索引。
创新互联公司专注为客户提供全方位的互联网综合服务,包含不限于网站设计、成都网站设计、鹤岗网络推广、微信平台小程序开发、鹤岗网络营销、鹤岗企业策划、鹤岗品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们最大的嘉奖;创新互联公司为所有大学生创业者提供鹤岗建站搭建服务,24小时服务热线:18982081108,官方网址:www.cdcxhl.com
1、简单易学。
Go语言的作者本身就很懂C语言,所以同样Go语言也会有C语言的基因,所以对于程序员来说,Go语言天生就会让人很熟悉,容易上手。
2、并发性好。
Go语言天生支持并发,可以充分利用多核,轻松地使用并发。 这是Go语言最大的特点。
描述
Go的语法接近C语言,但对于变量的声明有所不同。Go支持垃圾回收功能。Go的并行模型是以东尼·霍尔的通信顺序进程(CSP)为基础,采取类似模型的其他语言包括Occam和Limbo,但它也具有Pi运算的特征,比如通道传输。
在1.8版本中开放插件(Plugin)的支持,这意味着现在能从Go中动态加载部分函数。
与C++相比,Go并不包括如枚举、异常处理、继承、泛型、断言、虚函数等功能,但增加了 切片(Slice) 型、并发、管道、垃圾回收、接口(Interface)等特性的语言级支持。
在go语言中使用viper之类的库很方便的处理yaml配置文件,但是在c语言中就比较麻烦,经过一番思索和借助强大的github,发现了一个libyaml c库,但是网上的例子都比较麻烦,而且比较繁琐,就想法作了一个相对比较容易配置的解析应用,可以简单地类似viper 的模式进行配置实现不同的配置文件读取。如你的配置文件很复杂请按格式修改KeyValue 全局变量,欢迎大家一起完善
库请自行下载 GitHub - yaml/libyaml: Canonical source repository for LibYAML
直接上代码
yaml示例文件
%YAML 1.1
---
mqtt:
subtopic: "Control/#"
pubtopic: "bbt"
qos: 1
serveraddress: "tcp://192.168.0.25:1883"
clientid: "kvm_test"
writelog: false
writetodisk: false
outputfile: "./receivedMessages.txt"
hearttime: 30
#ifndef __CONFIG_H__
#define __CONFIG_H__
#ifdef __cplusplus
extern "C" {
#endif
/************************/
/* Minimum YAML version */
/************************/
#define YAML_VERSION_MAJOR 1
#define YAML_VERSION_MINOR 1
#define STRUCT_TYPE_NAME 100
#define INT_TYPE_NAME 101
#define STRING_TYPE_NAME 102
#define BOOL_TYPE_NAME 103
#define FLOAT_TYPE_NAME 104
#define MAP_TYPE_NAME 105
#define LIST_TYPE_NAME 106
typedef struct{
char *key;
void *value;
int valuetype;
char *parent;
}KeyValue,*pKeyValue;
#ifdef __cplusplus
}
#endif
#endif
#include
#include
#include
#include
#include
#include
#include
#include "config.h"
typedef struct {
char *SUBTOPIC; //string `yaml:"subtopic" mapstructure:"subtopic"` //"topic1"
char *PUBTOPIC; //string `yaml:"pubtopic" mapstructure:"pubtopic"`
int QOS; //byte `yaml:"qos" mapstructure:"qos"` //1
char *SERVERADDRESS; //string `yaml:"serveraddress" mapstructure:"serveraddress"` //= "tcp://mosquitto:1883"
char *CLIENTID; //string `yaml:"clientid" mapstructure:"clientid"` //= "mqtt_subscriber"
int HEARTTIME; //int `yaml:"hearttime" mapstructure:"hearttime"`
// CommandLocalPath string `yam:"commanlocalpath"`
}mqttSection,*pmqttSection;
typedef struct {
mqttSection Mqtt;// `yaml:"mqtt" mapstructure:"mqtt"`
// KVM kvmSection `yaml:"kvm" mapstructure:"kvm"`
}ConfigT;
ConfigT config;
static KeyValue webrtcconfig[]={
{"mqtt",config,STRUCT_TYPE_NAME,NULL},
{"subtopic",(config.Mqtt.SUBTOPIC),STRING_TYPE_NAME,"mqtt"},
{"pubtopic",(config.Mqtt.PUBTOPIC),STRING_TYPE_NAME,"mqtt"},
{"qos",(config.Mqtt.QOS),INT_TYPE_NAME,"mqtt"},
{"serveraddress",(config.Mqtt.SERVERADDRESS),STRING_TYPE_NAME,"mqtt"},
{"clientid",(config.Mqtt.CLIENTID),STRING_TYPE_NAME,"mqtt"},
{"hearttime",(config.Mqtt.HEARTTIME),INT_TYPE_NAME,"mqtt"},
{NULL,NULL,0,NULL},
};
int printConfig(ConfigT * pconfig){
if(pconfig==NULL) return -1;
printf("mqtt:r ");
if(pconfig-Mqtt.SUBTOPIC!=NULL) {printf("subtopic: %sr ",pconfig-Mqtt.SUBTOPIC); }
if(pconfig-Mqtt.SUBTOPIC!=NULL) {printf("pubtopic: %sr ",pconfig-Mqtt.PUBTOPIC); }
printf("qos: %dr ",config.Mqtt.QOS);
if(pconfig-Mqtt.SERVERADDRESS!=NULL) {printf("serveraddress: %sr ",pconfig-Mqtt.SERVERADDRESS); }
if(pconfig-Mqtt.CLIENTID!=NULL) {printf("clientid: %sr ",pconfig-Mqtt.CLIENTID); }
printf("hearttime: %dr ",config.Mqtt.HEARTTIME);
}
int freeConfig(ConfigT * pconfig){
if(pconfig==NULL) return -1;
if(pconfig-Mqtt.SERVERADDRESS!=NULL) {free(pconfig-Mqtt.SERVERADDRESS); }
if(pconfig-Mqtt.CLIENTID!=NULL) {free(pconfig-Mqtt.CLIENTID); }
if(pconfig-Mqtt.SUBTOPIC!=NULL) {free(pconfig-Mqtt.SUBTOPIC); }
}
char currentkey[100];
void getvalue(yaml_event_t event,pKeyValue *ppconfigs){
char *value = (char *)event.data.scalar.value;
pKeyValue pconfig=*ppconfigs;
char *pstringname;
while(pconfig-key!=NULL){
if(currentkey[0]!=0){
if(!strcmp(currentkey,pconfig-key))
{
switch(pconfig-valuetype){
case STRING_TYPE_NAME:
pstringname=strdup(value);
printf("get string value %sr ",pstringname);
*((char**)pconfig-value)=pstringname;
memset(currentkey, 0, sizeof(currentkey));
break;
case INT_TYPE_NAME:
*((int*)(pconfig-value))=atoi(value);
memset(currentkey, 0, sizeof(currentkey));
break;
case BOOL_TYPE_NAME:
if(!strcmp(value,"true")) *((bool*)(pconfig-value))=true;
else *((bool*)(pconfig-value))=false;
memset(currentkey, 0, sizeof(currentkey));
break;
case FLOAT_TYPE_NAME:
*((float*)(pconfig-value))=atof(value);
memset(currentkey, 0, sizeof(currentkey));
break;
case STRUCT_TYPE_NAME:
case MAP_TYPE_NAME:
case LIST_TYPE_NAME:
memset(currentkey, 0, sizeof(currentkey));
strncpy(currentkey,value,strlen(value));
break;
default:
break;
}
break;
}
//continue;
}else{
if(!strcmp(value,pconfig-key)){
strncpy(currentkey,pconfig-key,strlen(pconfig-key));
break;
}
}
pconfig++;
}
}
int Load_YAML_Config( char *yaml_file, KeyValue *(configs[]) )
{
struct stat filecheck;
yaml_parser_t parser;
yaml_event_t event;
bool done = 0;
unsigned char type = 0;
unsigned char sub_type = 0;
if (stat(yaml_file, filecheck) != false )
{
printf("[%s, line %d] Cannot open configuration file '%s'! %s", __FILE__, __LINE__, yaml_file, strerror(errno) );
return -1;
}
FILE *fh = fopen(yaml_file, "r");
if (!yaml_parser_initialize(parser))
{
printf("[%s, line %d] Failed to initialize the libyaml parser. Abort!", __FILE__, __LINE__);
return -1;
}
if (fh == NULL)
{
printf("[%s, line %d] Failed to open the configuration file '%s' Abort!", __FILE__, __LINE__, yaml_file);
return -1;
}
memset(currentkey, 0, sizeof(currentkey));
/* Set input file */
yaml_parser_set_input_file(parser, fh);
while(!done)
{
if (!yaml_parser_parse(parser, event))
{
/* Useful YAML vars: parser.context_mark.line+1, parser.context_mark.column+1, parser.problem, parser.problem_mark.line+1, parser.problem_mark.column+1 */
printf( "[%s, line %d] libyam parse error at line %ld in '%s'", __FILE__, __LINE__, parser.problem_mark.line+1, yaml_file);
}
if ( event.type == YAML_DOCUMENT_START_EVENT )
{
//yaml file first line is version
//%YAML 1.1
//---
yaml_version_directive_t *ver = event.data.document_start.version_directive;
if ( ver == NULL )
{
printf( "[%s, line %d] Invalid configuration file. Configuration must start with "%%YAML 1.1"", __FILE__, __LINE__);
}
int major = ver-major;
int minor = ver-minor;
if (! (major == YAML_VERSION_MAJOR minor == YAML_VERSION_MINOR) )
{
printf( "[%s, line %d] Configuration has a invalid YAML version. Must be 1.1 or above", __FILE__, __LINE__);
return -1;
}
}
else if ( event.type == YAML_STREAM_END_EVENT )
{
done = true;
}
else if ( event.type == YAML_MAPPING_END_EVENT )
{
sub_type = 0;
}
else if ( event.type == YAML_SCALAR_EVENT )
{
getvalue(event,configs);
}
}
return 0;
}
int main(int argc, char *argv[]){
pKeyValue pconfig=webrtcconfig[0];
Load_YAML_Config("../../etc/kvmagent.yml",pconfig);
printConfig(config);
freeConfig(config);
}
您好,gcc_start函数是GCC(GNU Compiler Collection)中的一个函数,它是一个开源的编译器,用于编译C、C++、Objective-C、Fortran、Java、Ada和Go语言。gcc_start函数是GCC中的一个重要函数,它主要是用来初始化编译器,它会把编译器的参数设置好,并且会把编译器的状态设置为可用状态。gcc_start函数还会把编译器的缓存设置好,以便编译器能够正确地识别编译器的参数。此外,gcc_start函数还会把编译器的缓存设置好,以便编译器能够正确地识别编译器的参数。gcc_start函数还会把编译器的缓存设置好,以便编译器能够正确地识别编译器的参数。最后,gcc_start函数还会把编译器的缓存设置好,以便编译器能够正确地识别编译器的参数。
Cgo 使得Go程序能够调用C代码. cgo读入一个用特别的格式写的Go语言源文件, 输出Go和C程序, 使得C程序能打包到Go语言的程序包中.
举例说明一下. 下面是一个Go语言包, 包含了两个函数 -- Random 和 Seed -- 是C语言库中random和srandom函数的马甲.
package rand
/*
#include stdlib.h
*/ import "C" func Random() int { return int(C.random()) } func Seed(i int) { C.srandom(C.uint(i)) }
我们来看一下这里都有什么内容. 开始是一个包的导入语句.
rand包导入了"C"包, 但你会发现在Go的标准库里没有这个包. 那是因为C是一个"伪包", 一个为cgo引入的特殊的包名, 它是C命名空间的一个引用.
rand 包包含4个到C包的引用: 调用 C.random和C.srandom, 类型转换 C.uint(i)还有引用语句.
Random函数调用libc中的random函数, 然后回返结果. 在C中, random返回一个C类型的长整形值, cgo把它轮换为C.long. 这个值必需转换成Go的类型, 才能在Go程序中使用. 使用一个常见的Go类型转换:
func Random() int { return int(C.random()) }
这是一个等价的函数, 使用了一个临时变量来进行类型转换:
func Random() int { var r C.long = C.random() return int(r) }
Seed函数则相反. 它接受一个Go语言的int类型, 转换成C语言的unsigned int类型, 然后传递给C的srandom函数.
func Seed(i int) { C.srandom(C.uint(i)) }
需要注意的是, cgo中的unsigned int类型写为C.uint; cgo的文档中有完整的类型列表.
这个例子中还有一个细节我们没有说到, 那就是导入语句上面的注释.
/*
#include stdlib.h
*/ import "C"
Cgo可以识别这个注释, 并在编译C语言程序的时候将它当作一个头文件来处理. 在这个例子中, 它只是一个include语句, 然而其实它可以是使用有效的C语言代码. 这个注释必需紧靠在import "C"这个语句的上面, 不能有空行, 就像是文档注释一样.
Strings and things
与Go语言不同, C语言中没有显式的字符串类型. 字符串在C语言中是一个以0结尾的字符数组.
Go和C语言中的字符串转换是通过C.CString, C.GoString,和C.GoStringN这些函数进行的. 这些转换将得到字符串类型的一个副本.
下一个例子是实现一个Print函数, 它使用C标准库中的fputs函数把一个字符串写到标准输出上:
package print // #include stdio.h // #include stdlib.h import "C" import "unsafe" func Print(s string) { cs := C.CString(s) C.fputs(cs, (*C.FILE)(C.stdout)) C.free(unsafe.Pointer(cs)) }
在C程序中进行的内存分配是不能被Go语言的内存管理器感知的. 当你使用C.CString创建一个C字符串时(或者其它类型的C语言内存分配), 你必需记得在使用完后用C.free来释放它.
调用C.CString将返回一个指向字符数组开始处的指错, 所以在函数退出前我们把它转换成一个unsafe.Pointer(Go中与C的void 等价的东西), 使用C.free来释放分配的内存. 一个惯用法是在分配内存后紧跟一个defer(特别是当这段代码比较复杂的时候), 这样我们就有了下面这个Print函数:
func Print(s string) { cs := C.CString(s) defer C.free(unsafe.Pointer(cs)) C.fputs(cs, (*C.FILE)(C.stdout)) }
构建 cgo 包
如果你使用goinstall, 构建cgo包就比较容易了, 只要调用像平常一样使用goinstall命令, 它就能自动识别这个特殊的import "C", 然后自动使用cgo来编译这些文件.
如果你想使用Go的Makefiles来构建, 那在CGOFILES变量中列出那些要用cgo处理的文件, 就像GOFILES变量包含一般的Go源文件一样.
rand包的Makefile可以写成下面这样:
include $(GOROOT)/src/Make.inc
TARG=goblog/rand
CGOFILES=\ rand.go\ include $(GOROOT)/src/Make.pkg
然后输入gomake开始构建.
更多 cgo 的资源
cgo的文档中包含了关于C伪包的更多详细的说明, 以及构建过程. Go代码树中的cgo的例子给出了更多更高级的用法.
一个简单而又符合Go惯用法的基于cgo的包是Russ Cox写的gosqlite. 而Go语言的网站上也列出了更多的的cgo包.
最后, 如果你对于cgo的内部是怎么运作这个事情感到好奇的话, 去看看运行时包的cgocall.c文件的注释吧.
如果你使用的是Visual C++的话
点击一个标准库里的类、库函数或者宏,按F12 或者鼠标右键 go to defnition 可以看到定义
别的编译器不太了解
但是所有的编译器到安装路径下找头文件所在的文件夹肯定是找得到的