在读TNN/MACE代码时总看到动态加载相关代码,因此在这做一个总结和试用。代码参考windows动态加载和linux动态加载
通过dlsym/getprocaddress获取动态库的函数地址,然后利用该地址进行其它相关操作(重命名函数之类的)。
#ifdef WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include "CL/cl.h"
typedef CL_API_ENTRY cl_int(CL_API_CALL *clGetPlatformIDsFuncPtr)(
cl_uint /* num_entries */,
cl_platform_id * /* platforms */,
cl_uint * /* num_platforms */) CL_API_SUFFIX__VERSION_1_0;
typedef CL_API_ENTRY cl_int(CL_API_CALL *clGetPlatformInfoFuncPtr)(
cl_platform_id /* platform */,
cl_platform_info /* param_name */,
size_t /* param_value_size */,
void * /* param_value */,
size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
static clGetPlatformIDsFuncPtr clGetPlatformIDsPtr = NULL;
static clGetPlatformInfoFuncPtr clGetPlatformInfoPtr = NULL;
#define clGetPlatformInfo clGetPlatformInfo_Test
cl_int CL_API_CALL clGetPlatformInfo_Test(
cl_platform_id platform,
cl_platform_info param_name,
size_t param_value_size,
void *param_value,
size_t *param_value_size_ret)
{
return (clGetPlatformInfoPtr)(platform, param_name, param_value_size, param_value, param_value_size_ret);
}
int main()
{
#ifdef WIN32
HINSTANCE ocl_lib = LoadLibrary(TEXT("opencl.dll"));
if (!ocl_lib)
{
printf("Load Library failed\n");
}
clGetPlatformIDsPtr = (clGetPlatformIDsFuncPtr)(GetProcAddress(ocl_lib, "clGetPlatformIDs"));
clGetPlatformInfoPtr = (clGetPlatformInfoFuncPtr)(GetProcAddress(ocl_lib, "clGetPlatformInfo"));
#else
void* ocl_lib = dlopen("libOpenCL.so", RTLD_NOW);
if (!ocl_lib)
{
printf("Load Library failed\n");
}
clGetPlatformIDsPtr = (clGetPlatformIDsFuncPtr)(dlsym(ocl_lib, "clGetPlatformIDs"));
clGetPlatformInfoPtr = (clGetPlatformInfoFuncPtr)(dlsym(ocl_lib, "clGetPlatformInfo"));
#endif
unsigned int num = 0;
int iRslt = clGetPlatformIDsPtr(0, NULL, &num);
cl_platform_id* platform_id = (cl_platform_id*)malloc(num * sizeof(cl_platform_id));
iRslt = clGetPlatformIDsPtr(num, platform_id, NULL);
cl_platform_id cl_platform = platform_id[0];
free(platform_id);
char platname[50];
clGetPlatformInfo(cl_platform, CL_PLATFORM_NAME, 50 * sizeof(char),
platname, NULL);
#ifdef WIN32
FreeLibrary(ocl_lib);
#else
dlclose(ocl_lib);
#endif
printf("%s\n", platname);
return iRslt;
}
Windows动态链接库DLL
1.什么是DLL
DLL,即动态链接库,是包含若干个函数的库文件,可供其他程序运行时调用。
2.DLL的优缺点
优点:代码重用,可供多个程序同时调用
缺点:易发生版本冲突
当新版本的动态链接库不兼容旧版本时,其他使用该DLL的程序可能无法正常工作。
针对这一问题,我们需要在程序中加上一个manifest文件,指明该程序所使用的DLL版本号。
此时,程序将根据manifest加载指定版本的DLL,否则按默认版本加载。
3.关于LIB和DLL
LIB,是静态链接库,分为静态lib和动态lib。
静态lib:包含函数代码声明和实现,编译后所有代码都嵌入到宿主程序中。不需要再另行调用DLL。
动态lib:相当于一个.h头文件,它是对实现部分(.DLL)的导出部分的声明。编译后宿主程序也只包括声明部分。运行时需调用相应的DLL文件。
1 #ifndef _MYMATH_H 2 #define _MYMATH_H 3 #include <stdio.h> 4 5 6 #ifdef MYMATHDLL_EXPORT 7 #define MYMATHDLL_API _declspec(dllexport) 8 #else 9 #define MYMATHDLL_API _declspec(dllimport) 10 #endif // end of MYMATHDLL_EXPORT 11 12 #ifdef __cplusplus 13 extern "C" { 14 #endif // end of __cplusplus 15 16 int MYMATHDLL_API Add(int a, int b); 17 18 int MYMATHDLL_API Sub(int a, int b); 19 20 int MYMATHDLL_API Mul(int a, int b); 21 22 int MYMATHDLL_API Div(int a, int b); 23 24 #ifdef __cplusplus 25 } 26 #endif // end of __cplusplus 27 28 29 30 #endif// end of _MYMATH_H
1 #include "stdafx.h" 2 3 #define MYMATHDLL_EXPORT 4 #include "MyMath.h" 5 #include <stdio.h> 6 7 8 9 int Add(int a, int b) 10 { 11 printf("Call %s ", __FUNCTION__); 12 return a + b; 13 } 14 15 int Sub(int a, int b) 16 { 17 printf("Call %s ", __FUNCTION__); 18 return a - b; 19 } 20 21 int Sub(int a, int b, int c) 22 { 23 return a + b + c; 24 } 25 26 int Mul(int a, int b) 27 { 28 printf("Call %s ", __FUNCTION__); 29 return a * b; 30 } 31 32 int Div(int a, int b) 33 { 34 printf("Call %s ", __FUNCTION__); 35 return a / b; 36 }
main
1 #include <iostream> 2 #include <Windows.h> 3 4 #include "MyMath.h" 5 #pragma comment(lib, "DllTest.lib") 6 7 void ExplicitCall(); 8 void ImplicitCall(); 9 10 int main() 11 { 12 std::cout << "Hello World! "; 13 ImplicitCall(); 14 //ExplicitCall(); 15 return 0; 16 } 17 18 void ExplicitCall() 19 { 20 typedef int(*pAdd)(int a, int b); 21 22 typedef int(*pSub)(int a, int b); 23 24 HINSTANCE hDll = NULL; 25 pAdd _Add = NULL; 26 pSub _Sub = NULL; 27 28 29 hDll = LoadLibrary(L"DllTest"); 30 31 if (hDll == NULL) std::cout << "failed to call LoadLibrary "; 32 33 DWORD lastError = 0; 34 35 if ((_Add = (pAdd)GetProcAddress(hDll, "Add")) == NULL) 36 { 37 std::cout << "failed to call GetProcAddress Add " << std::endl; 38 lastError = GetLastError(); 39 std::cout << "Add lastError = " << lastError << std::endl; 40 } 41 42 43 if ((_Sub = (pSub)GetProcAddress(hDll, "Sub")) == NULL) 44 { 45 std::cout << "failed to call GetProcAddress Sub " << std::endl; 46 lastError = GetLastError(); 47 std::cout << "Sub lastError = " << lastError << std::endl; 48 } 49 50 int a = 10, b = 6, c = 17; 51 int addVal = _Add(a, b); 52 53 int subVal = _Sub(a, b); 54 55 std::cout << "addVal = " << addVal << ", subVal = " << subVal << std::endl; 56 FreeLibrary(hDll); 57 } 58 59 void ImplicitCall() 60 { 61 62 int a = 10, b = 6, c = 17; 63 int sum = Add(a, b); 64 int sub = Sub(a, b); 65 std::cout << "addVal = " << sum << ", subVal = " << sub << std::endl; 66 }