专栏首页纸上得来终觉浅libuv源码阅读(13)--plugin
原创

libuv源码阅读(13)--plugin

先看下用例源码:

main.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <uv.h>

#include "plugin.h"

typedef void (*init_plugin_function)();

void mfp_register(const char *name) {
    fprintf(stderr, "Registered plugin \"%s\"\n", name);
}

int main(int argc, char **argv) {
    if (argc == 1) {
        fprintf(stderr, "Usage: %s [plugin1] [plugin2] ...\n", argv[0]);
        return 0;
    }

    uv_lib_t *lib = (uv_lib_t*) malloc(sizeof(uv_lib_t));
    while (--argc) {
        fprintf(stderr, "Loading %s\n", argv[argc]);
        if (uv_dlopen(argv[argc], lib)) {
            fprintf(stderr, "Error: %s\n", uv_dlerror(lib));
            continue;
        }

        init_plugin_function init_plugin;
        if (uv_dlsym(lib, "initialize", (void **) &init_plugin)) {
            fprintf(stderr, "dlsym error: %s\n", uv_dlerror(lib));
            continue;
        }

        init_plugin();
    }

    return 0;
}

hello.c

#include "plugin.h"

void initialize() {
    mfp_register("Hello World!");
}

plugin.h

#ifndef UVBOOK_PLUGIN_SYSTEM
#define UVBOOK_PLUGIN_SYSTEM

// Plugin authors should use this to register their plugins with mfp.
void mfp_register(const char *name);

#endif

功能很简单:载入启动参数中对应的插件动态库,调用它们的 initialize 方法

看下结构体:1个函数指针 一个错误消息指针

typedef struct {
  void* handle;
  char* errmsg;
} uv_lib_t;

然后看下实现:

static int uv__dlerror(uv_lib_t* lib);

// 连接动态库 得到引用句柄
int uv_dlopen(const char* filename, uv_lib_t* lib) {
  dlerror(); /* Reset error status. */
  lib->errmsg = NULL;
  lib->handle = dlopen(filename, RTLD_LAZY);
  return lib->handle ? 0 : uv__dlerror(lib);
}


void uv_dlclose(uv_lib_t* lib) {
  uv__free(lib->errmsg);
  lib->errmsg = NULL;

  if (lib->handle) {
    /* Ignore errors. No good way to signal them without leaking memory. */
    dlclose(lib->handle);
    lib->handle = NULL;
  }
}

// 获取句柄指定方法 注意第三个参数 修改指传入ptr指针所指向 函数指针
int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) {
  dlerror(); /* Reset error status. */
  *ptr = dlsym(lib->handle, name);
  return uv__dlerror(lib);
}


const char* uv_dlerror(const uv_lib_t* lib) {
  return lib->errmsg ? lib->errmsg : "no error";
}


static int uv__dlerror(uv_lib_t* lib) {
  const char* errmsg;

  uv__free(lib->errmsg);

  errmsg = dlerror();

  if (errmsg) {
    lib->errmsg = uv__strdup(errmsg);
    return -1;
  }
  else {
    lib->errmsg = NULL;
    return 0;
  }
}

总结:主要就是演示如何使用动态加载库。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • libuv源码阅读(2)--queue.h

    这是一种双向队列的实现,假设现在有2个strcut BASE 和 A 要通过双向队列组织起来,BASE作为队列头结点的持有者,A作为队列元素插入:

    wanyicheng
  • libuv源码阅读(6)--helloworld

    每一种都是一种hanlder类型或者request类型,代表某种资源类型或者请求操作的包装结构体,里面的属性字段是为了支持它可以正常工作的而设置的:

    wanyicheng
  • libuv源码阅读(9)--interfaces

    简单来说就是调用linux系统的:getifaddrs 和 freeifaddrs,读取系统的网卡接口信息,然后拷贝到用户的缓冲区中,然后再释放函数内部的内存。...

    wanyicheng
  • libuv源码阅读(11)--lock

    2. 创建2个读者 1个写者 根据读写锁 被系统调度分配执行时机 输出对应自己的读到或者写后的值

    wanyicheng
  • libuv源码阅读(12)--change

    可以看到 fs_event_s 也是由基础的handler和一个path 以及 它独有的字段组成

    wanyicheng
  • libuv源码阅读(16)--signal

    总结:信号处理handler是被插入到红黑树中,按照一定规则排序插入的,信号越小,不带oneshot等规则。信号处理函数统一触发信号管道可读,然后loop从信号...

    wanyicheng
  • libuv源码阅读(18)--progress

    总结:用户自己初始化的async handler 也可以被插入到异步handler队列中,当管道[0]可读的时候,代表某个异步handler可以处理了,这时候遍...

    wanyicheng
  • libuv源码阅读(19)--vustop

    wanyicheng
  • libuv源码阅读(20)--uvcat

    wanyicheng

扫码关注云+社区

领取腾讯云代金券