之前没有做过包含类的dll的相关代码。第一次做,还是遇到很多问题,在此记录一下。
刚开始没有定义虚基类为接口类,导致编译时报错,无法解析XXXXX。
正确做法:
首先定义一个接口类,注意,析构函数为虚函数,其他方法为纯虚函数。
class NVGpuMon
{
public:
virtual ~NVGpuMon(void){};
NVGpuMon(void){};
//
//get describing the version of the NvAPI library
//
virtual bool GetInterfaceVersionString(LPSTR strVer) = 0;
//
//This function returns a struct that describes aspects of the display driver build.
//
virtual bool GetDisplayDriverVersion() = 0;
//
//Get physical gpu count
//
virtual int GetPhyGpuCount() = 0;
}
然后在此头文件中,导出接口
//接口
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
NVGPUMON_API NVGpuMon* NVGpuMonCreate(void);
NVGPUMON_API void NVGpuMonDestroy(NVGpuMon*);
#ifdef __cplusplus
}
#endif // __cplusplus
然后,定义一个实现类,继承以上接口。
class NVGpuMonImp : public NVGpuMon
{
public:
~NVGpuMonImp(void);
public:
NVGpuMonImp(void);
public:
//
//get describing the version of the NvAPI library
//
bool GetInterfaceVersionString(LPSTR strVer);
//
//This function returns a struct that describes aspects of the display driver build.
//
bool GetDisplayDriverVersion();
//
//Get physical gpu count
//
int GetPhyGpuCount();
}
并在cpp中
实现其方法,以及接口的实现:
NVGpuMon* NVGpuMonCreate()
{
NVGpuMon * pInstance = new NVGpuMonImp();//返回子类
if (pInstance != NULL)
return pInstance;
}
void NVGpuMonDestroy(NVGpuMon* pInstance)
{
if (pInstance != NULL)
delete pInstance;
}
最后就可以编译生成dll了。
完整的测试程序,
#include"include/NVGpuMonAPI.h"
typedef NVGpuMon* (*PNVGPUMONCREATE)();
typedef void (*PNVGPUMONDESTROY)(NVGpuMon *);
typedef struct _NVGPUMON
{
PNVGPUMONCREATE m_NVGpuMonCreate;
PNVGPUMONDESTROY m_NVGpuMonDestroy;
}NVGPUMON;
NVGPUMON *m_pNVGpuMon = NULL;
NVGpuMon *m_pNVGpuMonIns = NULL;//实例
void *_pNVApiDll = NULL;
#define _WIN64 1
bool load_nvgpumon_lib()
{
#if _WIN64
#ifdef UNICODE
static LPCWSTR __NVApiDllName = L"../dll/x64/NVGpuMon.dll";
#else
static LPCSTR __NVApiDllName = "../dll/x64/NVGpuMon.dll";
#endif//UNICODE
#else _WIN32
#ifdef UNICODE
static LPCWSTR __NVApiDllName = L"../dll/x86/NVGpuMon.dll";
#else
static LPCSTR __NVApiDllName = "../dll/x86/NVGpuMon.dll";
#endif//UNICODE
#endif
_pNVApiDll = LoadLibrary(__NVApiDllName);
if (_pNVApiDll == NULL)
{
printf("%s : %s LoadLibrary failed, please check file, line: %d\n", __FILE__, __FUNCTION__, __LINE__);
printf("error code: %d\n", GetLastError());
return false;
}
else
{
if (m_pNVGpuMon == NULL)
{
try{
m_pNVGpuMon = new NVGPUMON;
}
catch (const std::bad_alloc& e)
{
printf("%s : %s malloc error:%s, line:%d!\n", __FILE__, __FUNCTION__, e.what(), __LINE__);
}
}
if (m_pNVGpuMon == NULL)
{
printf("%s : %s malloc error, line:%d!\n", __FILE__, __FUNCTION__, __LINE__);
return false;
}
memset(m_pNVGpuMon, 0, sizeof(m_pNVGpuMon));
m_pNVGpuMon->m_NVGpuMonCreate = (PNVGPUMONCREATE)GetProcAddress((HMODULE)_pNVApiDll, "NVGpuMonCreate");
m_pNVGpuMon->m_NVGpuMonDestroy = (PNVGPUMONDESTROY)GetProcAddress((HMODULE)_pNVApiDll, "NVGpuMonDestroy");
if (m_pNVGpuMon->m_NVGpuMonCreate == NULL || m_pNVGpuMon->m_NVGpuMonDestroy == NULL)
{
printf("%s : %s NVGpuMon GetProcAddress failed, line: %d\n", __FILE__, __FUNCTION__, __LINE__);
}
}
return true;
}
bool Init()
{
if (!load_nvgpumon_lib())
return false;
if (m_pNVGpuMon->m_NVGpuMonCreate == NULL)
{
printf("%s : %s invalid param, line: %d\n", __FILE__, __FUNCTION__, __LINE__);
return false;
}
m_pNVGpuMonIns = m_pNVGpuMon->m_NVGpuMonCreate();
if (m_pNVGpuMonIns == NULL)
{
printf("%s : %s NVGpuMon create failed, line: %d\n", __FILE__, __FUNCTION__, __LINE__);
return false;
}
}
bool Destroy()
{
if (m_pNVGpuMon->m_NVGpuMonDestroy == NULL || m_pNVGpuMonIns == NULL)
{
printf("%s : %s invalid param, line: %d\n", __FILE__, __FUNCTION__, __LINE__);
return false;
}
m_pNVGpuMon->m_NVGpuMonDestroy(m_pNVGpuMonIns);
m_pNVGpuMonIns = NULL;
if (m_pNVGpuMon != NULL)
delete m_pNVGpuMon;
if (_pNVApiDll)
{
FreeLibrary((HMODULE)_pNVApiDll);
_pNVApiDll = NULL;
}
return true;
}
int main()
{
if (!Init())
{
printf("pinit failed \n");
getchar();
return -1;
}
int phyCount = m_pNVGpuMonIns->GetPhyGpuCount();
printf("nvidia gpu number: %d\n",phyCount);
NV_GPU_DYNAMIC_PSTATES_INFO_EX PstatesInfo;
if (phyCount > 0)
while (1)
{
if(m_pNVGpuMonIns->GetGpuDynamicInfo(0, PstatesInfo) == 0)
printf("percentage:%d%c\n", PstatesInfo.utilization[0].percentage, '%');
else
printf("get percentage error \n");
Sleep(1000);
}
getchar();
return 0;
}