linux下so编写 - 动态库-类

linux下so编写 - 动态库-类

引言

加载类有点困难,因为我们需要类的一个实例,而不仅仅是一个函数指针。我们无法通过new来创建类的实例,因为类是在动态库中定义的而不是在可执行程序中定义的,况且有时候我们连动态库中具体的类的名字都不知道。

解决方案是:利用多态性!我们在可执行文件中定义一个带虚成员函数的接口基类,而在模块中定义派生实现类。通常来说,接口类是抽象的(如果一个类含有虚函数,那它就是抽象的)。因为动态加载类往往用于实现插件,这意味着必须提供一个清晰定义的接口──我们将定义一个接口类和派生实现类。

接下来,在模块中,我们会定义两个附加的类工厂函数(class factory functions)(或称对象工厂函数)。其中一个函数创建一个类实例,并返回其指针;另一个函数则用以销毁该指针。这两个函数都以extern "C"来限定修饰。

代码

  • testso.h
/**********************************************************************************
 *	最上层的接口:c接口用于创建父类、销毁父类
 *  父类:用于c函数的调用创建与销毁
 *  子类:真正使用的
 *  调用完毕
 **********************************************************************************/

#ifndef _TESTSO_H_
#define _TESTSO_H_

// 只能通过基类调用,因此需要先定义一个基类,然后在create中生成真正需要生成的对象。

class CBase{
public:
	CBase() {};
	~CBase() {};

public:
    int a, b;
    virtual int add(void) = 0;
};

class Base : public CBase
{
public:
	Base() {};
	~Base() {};

public:
	virtual int add(void) {
		return -1;
	}
};

class A : public Base
{
public:
	A() {};
	~A() {};

public:
    int c;

public:
    int add(void);
};

typedef CBase* create_t(void);					// create factory
typedef void destory_t(CBase*);					// destory

#endif // _TESTSO_H_
	
  • testso.cpp
#include "testso.h"

int A::add(void)
{
    return a + b;
}

extern "C"
{
    CBase* create(void)				// 注意:create函数必须返回Base的对象,不能直接返回A的对象,否则后面调用A::add()的时候会提示错误。
    {
        return new A;
    }

    void destory(CBase *p)
    {
        if (p) delete p;
    }
}
		
  • main.cpp
#include <stdio.h> 
#include <stdlib.h>
#include <unistd.h>
#include <dlfcn.h>
#include "testso.h"

void print_usage(void)
{
    printf("Usage: myso SO_PATH/n");
}

int main(int argc, char *argv[])
{
    if (2 != argc) {
        print_usage();
        exit(0);
    }

    const char *soname = argv[1];

    void *so_handle = dlopen(soname, RTLD_LAZY);
    if (!so_handle) {
        fprintf(stderr, "Error: load so `%s' failed.\n", soname);
        exit(-1);
    }

    dlerror();
    create_t *create = (create_t*) dlsym(so_handle, "create");
    char *err = dlerror();
    if (NULL != err) {
        fprintf(stderr, "%s\n", err);
        exit(-1);
    }
    CBase *pa = create();

    pa->a = 57;
    pa->b = 3;
    //pa->c = 4;
    printf("A.add(57, 3)=%d\n", pa->add()); // 注意,这里通过虚函数实现了
                                            // 对A::add()的调用。

    destory_t *destory = (destory_t*) dlsym(so_handle, "destory");
    err = dlerror();
    if (NULL != err) {
        fprintf(stderr, "%s\n", err);
        exit(-1);
    }
    destory(pa);
    pa = NULL;

    dlclose(so_handle);

    printf("DONE!\n");
    return 0;
}
		
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值