c++在进行库开发的时候通常会依赖其它第三方库,或者是用c++部署深度学习模型时需要在库中加载深度学习模型。如果我们的库发布给业务端用,则需要把第三方库或者深度学习模型一并打包发送给业务端,并且还要配置好路径,这样做灵活性低,容易出错,很容易丢失依赖文件导致业务端实现不了功能。本文将记录一种方法,使用资源加载与释放的方式将第三方依赖库或深度学习模型一并发布给业务端使用。下面以文件followhand.onnx加载与释放为例:
1.c++ exe模式下的资源加载与释放
第一步:将鼠标移至项目名称位置,右键->添加->资源
第二步:导入资源,并输入资源类型(如:ONNX等)
第三步:打开resourse.h文件查看资源ID
操作完以上步骤接下来编写代码进行资源解析释放,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| #include <iostream> #include <cstdio> #include <cstdlib> #include <Windows.h> #include "resource.h"
using namespace std;
typedef VOID(*Func)(VOID);
BOOL ReleaseResource(UINT resourceId, TCHAR* resourceType, TCHAR* fileName) { HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(resourceId), resourceType); if (hRsrc == NULL) return FALSE; DWORD dwSize = SizeofResource(NULL, hRsrc); if (dwSize <= 0) return FALSE;
HGLOBAL hGlobal = LoadResource(NULL, hRsrc); if (hGlobal == NULL) return FALSE;
LPVOID lpRes = LockResource(hGlobal); if (lpRes == NULL) return FALSE;
HANDLE hFile = CreateFile(fileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == NULL) return FALSE;
DWORD dwWriten = 0; BOOL bRes = WriteFile(hFile, lpRes, dwSize, &dwWriten, NULL); if (bRes == FALSE || dwWriten <= 0) return FALSE;
CloseHandle(hFile); return TRUE; }
int main() { char ty_name[10] = "ONNX"; TCHAR TY_NAME[100];
#ifdef UNICODE MultiByteToWideChar(CP_ACP, 0, ty_name, -1, TY_NAME, 100); #else strcpy(TY_NAME, ty_name); #endif
char res_name[20] = "followhand.onnx"; TCHAR RES_NAME[200]; #ifdef UNICODE MultiByteToWideChar(CP_ACP, 0, res_name, -1, RES_NAME, 100); #else strcpy(RES_NAME, res_name); #endif
BOOL res = ReleaseResource(IDR_ONNX1, TY_NAME, RES_NAME);
return 0 ; }
|
ReleaseResource()函数会将资源释放到.exe同级目录下。
2.c++ dll模式下的资源加载与释放
上面我们在exe模式下获取释放了资源,但是如果在dll模式下ReleaseResource()函数中的FindResource()函数则会返回null,即找不到资源,查看错误码是1813。
出现上述问题的主要原因是FindResource()的文件句柄传递问题,在上面我们将文件句柄传递为NULL,即为.exe文件句柄,所以在dll模式下找不到我们要找的资源,因此我们需要获取我们的文件句柄,将其传递给FindResource()函数。获取文件句柄的方式是调用GetModuleHandle()函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #include <iostream> #include <cstdio> #include <cstdlib> #include <Windows.h> #include "../resource.h"
using namespace std;
typedef VOID(*Func)(VOID);
BOOL ReleaseResource(TCHAR* fileName) { HMODULE handle = GetModuleHandle(TEXT("dzFollowHandAI.dll"));
HRSRC hRsrc = FindResource(handle, MAKEINTRESOURCE(IDR_ONNX1), TEXT("ONNX")); if (hRsrc == NULL) return FALSE;
DWORD dwSize = SizeofResource(handle, hRsrc); if (dwSize <= 0) return FALSE;
HGLOBAL hGlobal = LoadResource(handle, hRsrc); if (hGlobal == NULL) return FALSE;
LPVOID lpRes = LockResource(hGlobal); if (lpRes == NULL) return FALSE; HANDLE hFile = CreateFile(fileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == NULL) return FALSE;
DWORD dwWriten = 0; BOOL bRes = WriteFile(hFile, lpRes, dwSize, &dwWriten, NULL); if (bRes == FALSE || dwWriten <= 0) return FALSE; CloseHandle(hFile); return TRUE; }
|
其它操作步骤同上。