在和别人合作开发的时候,往往存在一方提供库供另一方调用。这个过程存在编译依赖问题,库更新问题。为了解耦,这里可以使用dlopen的方式去使用动态库。
示例如下:
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <pthread.h>#include "abupdate.h"typedef int (*FuncptrType)(st_update_progress *);extern char *optarg;
extern int optind;
extern int opterr;
extern int optopt;const char getopt_str[] = "xz:y::";
static struct option long_options[] ={{"update", optional_argument, 0, 'a'},{"mask", optional_argument, 0, 'b'},{"switch_boot_slot", no_argument, 0, 'c'},{"cancel_switch_boot_slot", no_argument, 0, 'd'},{"set_current_slot_success", no_argument, 0, 'e'},{"rollback", no_argument, 0, 'f'},{"get_boot_slot", no_argument, 0, 'g'},{"help", no_argument, 0, 'h'},
};static int usage(void)
{printf("usage:\n");printf(" abupdate_app --help\n");printf(" abupdate_app --update=/data/update.zip --mask=0xff\n");printf(" abupdate_app --switch_boot_slot\n");printf(" abupdate_app --cancel_switch_boot_slot\n");printf(" abupdate_app --set_current_slot_success\n");printf(" abupdate_app --rollback\n");printf(" abupdate_app --get_boot_slot\n");return 0;
}// 此函数是一个回调函数,用于提供给底层库反馈升级进度
static int progress_callback(st_update_progress update_progress)
{printf("rollback total: %d%% soc: %d%% mcu:%d%% camera:%d%%\n", update_progress.total, update_progress.soc, update_progress.mcu, update_progress.camera);return 0;
}// 此函数主动调用获取升级进度的接口
static int thread_get_progress(void *arg)
{int ret = 0;st_update_progress update_progress;FuncptrType ge_progress_func = NULL;ge_progress_func = (FuncptrType)arg;while(1){ret = ge_progress_func(&update_progress);if(ret == 0){printf("total: %d%% soc: %d%% mcu:%d%% camera:%d%%\n", update_progress.total, update_progress.soc, update_progress.mcu, update_progress.camera);}else{printf("get progress error.\n");}sleep(1);}return 0;
}int main(int argc, char *argv[])
{int ret = 0;int opt = 0;int longindex = 0;int cmd = 0;char update_path[256] = {0};int upgrade_mask = 0;pthread_t thread_progress;void *handle = NULL;int (*update_func)(char *, progress_call_back_pointer, int);int (*ge_progress_func)(st_update_progress *);int (*switch_boot_slot_func)(void);int (*cancel_switch_boot_slot_func)(void);int (*set_current_slot_success_func)(void);int (*rollback_func)(void);int (*cancel_update_func)(void);int (*get_boot_slot_func)(void);while((opt = getopt_long(argc, argv, getopt_str, long_options, &longindex)) != -1){switch(opt){case 'a':memset(update_path, 0, sizeof(update_path));snprintf(update_path, sizeof(update_path), "%s", optarg);cmd = 'a';printf("update_path:%s\n", update_path);break;case 'b':upgrade_mask = strtol(optarg, NULL, 16);cmd = 'b';printf("upgrade_mask:0x%x\n", upgrade_mask);break;case 'c':cmd = 'c';printf("switch_boot_slot.\n");break;case 'd':cmd = 'd';printf("cancel_switch_boot_slot.\n");break;case 'e':cmd = 'e';printf("set_current_slot_success.\n");break;case 'f':cmd = 'f';printf("rollback.\n");break;case 'g':cmd = 'g';printf("get_boot_slot.\n");break;case 'h':usage();return 0;default:printf("cmd is error.\n");usage();return -1;}}handle = dlopen("libabupdate.so", RTLD_LAZY);if (handle == NULL){printf("dlerror:%s\n", dlerror());return -1;}dlerror();if(cmd == 'a' || cmd == 'b'){if(strlen(update_path) != 0 && upgrade_mask != 0){update_func = dlsym(handle, "ab_update");if(update_func == NULL){printf("dlerror:%s\n", dlerror());dlclose(handle);return -1;}ge_progress_func = dlsym(handle, "ab_get_progress");if(ge_progress_func == NULL){printf("dlerror:%s\n", dlerror());dlclose(handle);return -1;}ret = pthread_create(&thread_progress, NULL, thread_get_progress, ge_progress_func);ret = update_func(update_path, progress_callback, upgrade_mask);if(ret != 0){printf("ab_update failed\n");dlclose(handle);return -1;}pthread_cancel(thread_progress);printf("ab_update success\n");}}else if(cmd == 'c'){switch_boot_slot_func = dlsym(handle, "ab_switch_boot_slot");if(switch_boot_slot_func == NULL){printf("dlerror:%s\n", dlerror());dlclose(handle);return -1;}ret = switch_boot_slot_func();if(ret != 0){printf("switch_boot_slot failed\n");dlclose(handle);return -1;}printf("switch_boot_slot success\n");}else if(cmd == 'd'){cancel_switch_boot_slot_func = dlsym(handle, "ab_cancel_switch_boot_slot");if(cancel_switch_boot_slot_func == NULL){printf("dlerror:%s\n", dlerror());dlclose(handle);return -1;}ret = cancel_switch_boot_slot_func();if(ret != 0){printf("cancel_switch_boot_slot failed\n");dlclose(handle);return -1;}printf("cancel_switch_boot_slot success\n");}else if(cmd == 'e'){set_current_slot_success_func = dlsym(handle, "ab_set_current_slot_success");if(set_current_slot_success_func == NULL){printf("dlerror:%s\n", dlerror());dlclose(handle);return -1;}ret = set_current_slot_success_func();if(ret != 0){printf("set_current_slot_success failed\n");dlclose(handle);return -1;}printf("set_current_slot_success success\n");}else if(cmd == 'f'){rollback_func = dlsym(handle, "ab_rollback");if(rollback_func == NULL){printf("dlerror:%s\n", dlerror());dlclose(handle);return -1;}ret = rollback_func();if(ret != 0){printf("rollback failed\n");dlclose(handle);return -1;}printf("rollback success\n");}else if(cmd == 'g'){get_boot_slot_func = dlsym(handle, "ab_get_boot_slot");if(get_boot_slot_func == NULL){printf("dlerror:%s\n", dlerror());dlclose(handle);return -1;}ret = get_boot_slot_func();if(ret != 0){printf("get_boot_slot failed\n");dlclose(handle);return -1;}printf("get_boot_slot success\n");}else{usage();return -1;}return 0;
}/*** ./abupdate_app update.zip mask*/
#if 0
int main(int argc, char *argv[])
{int upgrade_mask = 0;int ret = 0;if (argc != 3){usage();return -1;}upgrade_mask = strtol(argv[2], NULL, 16);ret = ab_update(argv[1], progress_callback, upgrade_mask);if (ret != 0){printf("ab_update failed\n");return -1;}return 0;
}
#endif