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();
}