AWTK全称为Toolkit AnyWhere,是ZLG倾心打造的一套基于C语言开发的GUI框架。旨在为用户提供一个功能强大、高效可靠、简单易用、可轻松做出炫酷效果的GUI引擎,并支持跨平台同步开发,一次编程,终生使用。
看官网介绍可以免费用,唯一麻烦的就是需要注册账户,给key默认可以绑定3台机器
https://awtk.zlg.cn/注册账户后下载开发工具 https://awtk.zlg.cn/awstudio/download.html
安装包有win和linux,其他平台可能需要源码安装,就在deepinlinux20.9环境试了一下
按照例子建了一个空工程,加了按钮能切换语言,能读写控件值(text label),顺便加一下通过curl访问http接口的实例吧
首先安装curl库
sudo apt-get install libcurl4-openssl-dev
引用头文件
#include <curl/curl.h>
在编译C/C++程序时,添加以下链接选项,默认库在 /usr/lib/x86_64-linux-gnu/libcurl.so.4.5.0
-lcurl
在awtk里是配置sconstruct,将so库放在本项目里,再awtk的ide里编译调试都可以了
CUSTOM_WIDGET_LIBS = [{
"root" : '3rd/curl', # 第三方库路径,支持绝对路径和相对路径。
'shared_libs': ['curl'], # 引用的动态库名称,动态库文件必须放在 root/bin 目录下。
'static_libs': [] # 引用的静态库名称,静态库文件必须放在 root/lib 目录下。
}]
awtk的ide没有发布菜单,需要自己再工程根目录运行发布打包命令
python ./scripts/release.py
会将发布文件放到 ./release文件夹,这才是正规发布包内容
访问http接口一般返回json字符串,网上有c语言解析json
本工程用awtk开发,可以用awtk自带的,更简洁
#include "conf_io/conf_json.h"
tk_object_t* doc = conf_json_load("awtk1.json", TRUE);
printf("isSuccess:%d\n", tk_object_get_prop_bool(doc, "isSuccess",TRUE));
char buf[128]={0};
sprintf(buf,"%s",tk_object_get_prop_str(doc, "data"));
printf("data:%s\n", buf);
widget_set_text_utf8(edit, buf);
TK_OBJECT_UNREF(doc);
得到一个比较长字符串,为了方便显示,每10个字符加个空格显示
widget_t* target = WIDGET(e->target);
char buf[128]={0};
char newbuf[128]={0};
widget_get_text_utf8(target, buf, sizeof(buf)-1);
printf("data = %s\n", buf);
int i,j,t;
j=strlen(buf);
if(j>30){
t=0;
for(i=0;i<j;i++){
if(i>0 && (0==(i%10))){
newbuf[t]=' ';
t++;
}
newbuf[t]=buf[i];
t++;
}
printf("newbuf: %s \n",newbuf);
widget_set_text_utf8(label, newbuf);
}
最后也记录一下curl的2种get调用(直接保存成文件和回调保存到字符串)
#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
#include <string.h>
#include <unistd.h>
#include "conf_io/conf_json.h"
#include <ctype.h>
#define _XOPEN_SOURCE
#define __USE_XOPEN
struct MemoryStruct {
char *memory;
size_t size;
};
FILE *file;
widget_t* edit;
widget_t* label;
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct*) userp;
mem->memory = realloc(mem->memory, mem->size + realsize + 1);
if (mem->memory == NULL) {
/* out of memory! */
printf("not enough memory (realloc returned NULL)\n");
return 0;
}
memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
printf("get size %ld\n %s \n",mem->size , mem->memory);
file=fopen("awtk1.json","w");
fputs(mem->memory,file);
fclose(file);
tk_object_t* doc = conf_json_load("awtk1.json", TRUE);
printf("isSuccess:%d\n", tk_object_get_prop_bool(doc, "isSuccess",TRUE));
char buf[128]={0};
sprintf(buf,"%s",tk_object_get_prop_str(doc, "data"));
printf("data:%s\n", buf);
widget_set_text_utf8(edit, buf);
TK_OBJECT_UNREF(doc);
return realsize;
}
int httpsget(void)
{
CURL *curl = NULL;
CURLcode res;
struct MemoryStruct chunk;
chunk.memory = malloc(1); /* will be grown as needed by the realloc above */
chunk.size = 0; /* no data at this point */
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
curl = curl_easy_init();
if (!curl) {
return -1;
}
/*设置easy handle属性*/
/* specify URL */
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.64.251:8080/api/jc5000/getVersion");
/* Define our callback to get called when there's data to be written */
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
/* Set a pointer to our struct to pass to the callback */
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
/* set commom option */
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
/*执行数据请求*/
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
fprintf(stderr, "res=%d curl_easy_perform() failed: %s\n",res,curl_easy_strerror(res));
}
// 释放资源
free(chunk.memory);
curl_easy_cleanup(curl);
curl_global_cleanup();
return 0;
}
int gethttptofile() {
printf("Hello, gethttptofile!\n");
//1、curl全局初始化,初始化libcurl库(只能调用一次)
//CURL_GLOBAL_ALL尽可能初始化一切(除了CURL_GLOBAL_ACK_EINTR)
//CURL_GLOBAL_WIN32表示libcurl会初始化winsock库,如果失败则无法使用socket,windows系统专用
//CURL_GLOBAL_SSL初始化SSL,(不初始化可能无法使用https)
//CURL_GLOBAL_DEFAULT初始WIN32和SSL
//CURL_GLOBAL_ACK_EINTR设置此标志后,curl将在连接或等待数据时确认EINTR条件。否则,curl会等待直到完全超时。(在7.30.0中添加)
CURLcode init = curl_global_init(CURL_GLOBAL_ALL);
if(init!=CURLE_OK){
printf("curl全局初始化失败!\n");
exit(1);
}
//2、初始化curl,返回CURL句柄
CURL *curl = (struct CURL *)curl_easy_init();
if(curl==NULL){
printf("初始化CURL失败!\n");
exit(1);
}
//3、设置option,各种curl参数的
curl_easy_setopt(curl,CURLOPT_URL,"http://192.168.64.251:8080/test/getAppVersion");
//设置保存位置,使用临时文件或保存到fopen中
//FILE *
file=fopen("awtk1.log","w");
curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
//各option
// 1.CURLOPT_URL
// 设置访问URL
// 2.CURLOPT_WRITEFUNCTION,CURLOPT_WRITEDATA
// 通过设定一个回调函数,执行libcurl在接受到数据后用户想进行的操作,通常函数多做数据保存的功能,如处理下载文件。CURLOPT_WRITEDATA 用于表明CURLOPT_WRITEFUNCTION函数中的stream指针的来源,说白了就是设定回调函数的第四个参数的数据类型。回调函数原型为:size_t function( void *ptr, size_t size, size_t nmemb, void *stream);
// 3.CURLOPT_HEADERFUNCTION,CURLOPT_HEADERDATA
// 通过设定一个回调函数,执行libcurl在接受到http头数据后用户想进行的操作。CURLOPT_WRITEDATA 传递指针给libcurl,该指针表明CURLOPT_HEADERFUNCTION 函数的stream指针的来源。回调函数原型为 size_t function( void *ptr, size_t size,size_t nmemb, void *stream);
// 4.CURLOPT_READFUNCTION CURLOPT_READDATA
// libCurl需要读取数据传递给远程主机时将调用CURLOPT_READFUNCTION指定的函数,函数原型是:size_t function(void *ptr, size_t size, size_t nmemb,void *stream). CURLOPT_READDATA 表明CURLOPT_READFUNCTION函数原型中的stream指针来源,说白了就是设定回调函数的第四个参数的数据类型。
// 5.CURLOPT_NOPROGRESS,CURLOPT_PROGRESSFUNCTION,CURLOPT_PROGRESSDATA
// 跟数据传输进度相关的参数。CURLOPT_PROGRESSFUNCTION 指定的函数正常情况下每秒被libcurl调用一次,为了使CURLOPT_PROGRESSFUNCTION被调 用,CURLOPT_NOPROGRESS必须被设置为false,CURLOPT_PROGRESSDATA指定的参数将作为 CURLOPT_PROGRESSFUNCTION指定函数的第一个参数
// 6.CURLOPT_TIMEOUT,CURLOPT_CONNECTIONTIMEOUT:
// CURLOPT_TIMEOUT 用于设置传输时间,CURLOPT_CONNECTIONTIMEOUT 设置连接等待时间
// 7.CURLOPT_FOLLOWLOCATION
// 设置重定位URL
// CURLOPT_RANGE: CURLOPT_RESUME_FROM:
// 断点续传相关设置。CURLOPT_RANGE 指定char *参数传递给libcurl,用于指明http域的RANGE头域,例如:
// 表示头500个字节:bytes=0-499
// 表示第二个500字节:bytes=500-999
// 表示最后500个字节:bytes=-500
// 表示500字节以后的范围:bytes=500-
// 第一个和最后一个字节:bytes=0-0,-1
// 同时指定几个范围:bytes=500-600,601-999
// CURLOPT_RESUME_FROM 传递一个long参数给libcurl,指定你希望开始传递的偏移量。
// 8.CURLOPT_UPLOAD:
// 如果第三个参数被设置为1的话,就是让libcurl做好上传的准备。如果传输协议是http的话,uoload就是发送put。
// 9. CURLOPT_SSL_VERIFYPEER:
// 第三个参数的缺省值为1.该函数多用于设定curl忽略对网站证书的检查(不管忽略不忽略,curl都是检查的)。
// 10.CURLOPT_VERBOSE
// 相当厉害的一个参数,可以向控制台(默认)输出curl接受和发送的数据,输出流可以重定向。
// 11.CURLOPT_HTTPGET
// 将curl向服务器交互数据的方式改变为get
//4、执行curl的各种操作的请求
CURLcode curLcode = curl_easy_perform(curl);
if(curLcode!=CURLE_OK){
printf("curl请求失败:%d!\n",curLcode);
exit(1);
}
// perform错误码说明:
// 1.CURLE_OK
// 任务完成一切都好
// 2.CURLE_UNSUPPORTED_PROTOCOL
// 不支持的协议,由URL的头部指定
// 3.CURLE_COULDNT_CONNECT
// 不能连接到remote 主机或者代理
// 4.CURLE_REMOTE_ACCESS_DENIED
// 访问被拒绝
// 5.CURLE_HTTP_RETURNED_ERROR
// Http返回错误
// 6.CURLE_READ_ERROR
// 读本地文件错误
//5、读取请求响应的信息
long totalTime;
curLcode=curl_easy_getinfo(curl,CURLINFO_TOTAL_TIME,&totalTime);
if(curLcode!=CURLE_OK){
printf("curl获取信息失败:%d!\n",curLcode);
}
printf("CURLINFO_TOTAL_TIME:%ld!\n",totalTime);
// getinfo参数
// CURLINFO_EFFECTIVE_URL - 最后一个有效的URL地址
// CURLINFO_HTTP_CODE - 最后一个收到的HTTP代码
// CURLINFO_FILETIME - 远程获取文档的时间,如果无法获取,则返回值为"-1"
// CURLINFO_TOTAL_TIME - 最后一次传输所消耗的时间
// CURLINFO_NAMELOOKUP_TIME - 名称解析所消耗的时间
// CURLINFO_CONNECT_TIME - 建立连接所消耗的时间
// CURLINFO_PRETRANSFER_TIME - 从建立连接到准备传输所使用的时间
// CURLINFO_STARTTRANSFER_TIME - 从建立连接到传输开始所使用的时间
// CURLINFO_REDIRECT_TIME - 在事务传输开始前重定向所使用的时间
// CURLINFO_SIZE_UPLOAD - 以字节为单位返回上传数据量的总值
// CURLINFO_SIZE_DOWNLOAD - 以字节为单位返回下载数据量的总值
// CURLINFO_SPEED_DOWNLOAD - 平均下载速度
// CURLINFO_SPEED_UPLOAD - 平均上传速度
// CURLINFO_HEADER_SIZE - header部分的大小
// CURLINFO_HEADER_OUT - 发送请求的字符串
// CURLINFO_REQUEST_SIZE - 在HTTP请求中有问题的请求的大小
// CURLINFO_SSL_VERIFYRESULT - 通过设置CURLOPT_SSL_VERIFYPEER返回的SSL证书验证请求的结果
// CURLINFO_CONTENT_LENGTH_DOWNLOAD - 从Content-Length: field中读取的下载内容长度
// CURLINFO_CONTENT_LENGTH_UPLOAD - 上传内容大小的说明
// CURLINFO_CONTENT_TYPE - 下载内容的Content-Type:值,NULL表示服务器没有发送有效的Content-Type:header
//6、清理curl句柄
curl_easy_cleanup(curl);
//7、清理全局配置(只能调用一次)
curl_global_cleanup();
fclose(file);
file=fopen("awtk1.log","r");
//8、操作文件内容
//流指针移动到末尾
fseek(file,0,SEEK_END);
//返回当前流指针位置
const long i = ftell(file);
printf("文件长度:%ld!\n",i);
//计算完毕记得把流指针归位
rewind(file);
//申请一块能装下整个文件内容的内存区域
char *a = (char *) malloc(i);
//fgets(a, i+1,file);
fread(a, 1,i,file);
printf("当前文件内容:%s \n",a);
//记得释放申请的内存区域
free(a);
//关闭临时文件
fclose(file);
return 0;
}