C/C++ 动态库封装开发,含静态调用和动态调用

C/C++ 动态库封装开发

最近项目中遇到基于动态库的插件化开发,整理了一些资料,先贴代码,供大家一起参考~

静态调用

C++ 动态库封装开发

项目创建,选择C++空白项目,新建下列文件,修改项目为
在这里插入图片描述

动态库头文件(接口导出类):

#pragma once
#define FENGZHUANGCPP_API __declspec(dllexport)
//动态连接库
//静态连接库
class FENGZHUANGCPP_API IInterface
{
 public:
    static IInterface* CreateInterface();
    virtual void Init() = 0;
    virtual void Destroy() = 0;
    virtual char *GetName() = 0; 
}

源文件:

#include "Interface.h"
#include <iostream>
class FHello :public IInterface
{
public:
    FHello();
    virtual void Init();
    virtual void Destroy();
    virtual char* GetName() ;
private:
    char Name[1024];
};

FHello::FHello()
{
    memset(Name, 0, 1024);
    strcpy(Name,"Hello");  
}

void FHello::Init()
{
    printf("FHello::Init() \n");
}

void FHe1lo: :Destroy()
{
    printf("FHello::Destroy() \n");
}

char* FHe1lo::GetName()
{
    return Name;
}

IInterface* IInterface::CreateInterface()
{
    return new FHe1lo();
}

调用程序(静态调用):

#include "dlllib/Interface.h"
#include "Clib/Header.h"
#include <iostream>

#pragma comment(lib,"FengzhuangCpp.lib")
#pragma comment(lib,"FengzhuangC.lib")
using namespace std;
int main()
{
    //调用C++库
    IInterface *IF = IInterface::CreateInterface();
    cout << IF->GetName() << endl;
    IF->Init();
    IF->Destroy();
    
    //调用C库
    init_c(1, 2);
    get_c_name(2, 3 );
    return 0;
}

VS中需包含库路径
在这里插入图片描述

C语言动态库封装

动态库代码:
头文件部分:

#ifndef HEADER H
#define HEADER_H

#define FENZHUANGC_API  __decIspec(dllexport)

#ifdef __cplusplus
extern "C"    //告诉译器 这里面是c语言的代码
{
#endif
    FENZHUANGC_API int __stdcall init_c(int a,int b);
    FENZHUANGC_API int __stdcall get_c_name(int a, int b);
    int get_c_namel(int a, int b);#ifdefcplusplus
#ifdef __cplusplus
}
#endif

#endif

其中__stdcall为函数的调用约定
被这个关键字修饰的函数,其参数都是从右向左通过堆栈传递的(__fastcall 的前面部分由ecx,edx传), 函数调用在返回前要由被调用者清理堆栈。
这个关键字主要见于Microsoft Visual C、C++。GNU的C、C++是另外一种修饰方式:attribute((stdcall))
源文件:

#include "Header.h"
#include"stdio.h"
int __stdcall init_c(int a, int b)
{
    printf("%d %d",a,b);
    return 0;
}

int __stdcall get_c_name(int a, int b)
{
    printf("%d %d",a,b);
    return 0;
}

int get_c_name1(int a, int b)
{
    printf("%d %d",a,b);
    return 0;
}

调用方请看上方C++调用方例子

动态调用

动态库,
对外头文件:IAcoPlgInterface.h

#ifndef IACOPLGINTERFACE_H
#define IACOPLGINTERFACE_H


#include <QtCore/qglobal.h>
#include <QWidget>

#if defined(IACOPLGINTERFACE_LIBRARY)
#  define IACOPLGINTERFACE_EXPORT Q_DECL_EXPORT
#else
#  define IACOPLGINTERFACE_EXPORT Q_DECL_IMPORT  
#endif

class IAcoPlgInterface
{
public:

    /// @cond
    virtual ~IAcoPlgInterface() = default;
    /// @endcond

    /**
    * @brief 获取插件名称
    * @return 返回  插件名称
    */
    virtual QWidget* __stdcall init() = 0;

    /**
    * @brief 获取插件名称
    * @return 返回  插件名称
    */
    virtual QString __stdcall getPlgName() = 0;

    /**
    * @brief 卸载库
    */
    virtual void __stdcall unload() = 0;
};

// 需要提供一个创建该类的方法
// 由于显示调用必须通过函数名找到该方法,所以必须加 extern "C" 前缀,否则函数名会被改写,导致找不到该方法。
extern "C" IACOPLGINTERFACE_EXPORT IAcoPlgInterface* getPlgInstance();

#endif // ACOHPSMPLUGINS_H

源文件实现:Acohpsmplugins.cpp
调用程序基于Qt QLibrary开发,
主要代码:

#include "IAcoPlgInterface.h"  //引用头文件

typedef IAcoPlgInterface* (*func_getPlgInstance)();
{
    shared_ptr<QLibrary> pDll = make_shared<QLibrary>(_res);
    if (!pDll->load())
        continue;

    //获取插件实例
    auto getPlgInstance = (func_getPlgInstance)pDll->resolve("getPlgInstance");
    if (!getPlgInstance){
        continue;
    }
    //方法通过此函数调用
    IAcoPlgInterface* pinter =  getPlgInstance();
}
 
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值