在官网上下下来包过后,官网的安装说明不全:
// stdcall & cdecl
#if defined(_MSC_VER) || defined(_WIN32) || defined(_WIN)
#define TCE_API __stdcall
// TCELOGGER_DLL_EXPORTS
#ifdef TCELOGGER_DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
#else
#define TCE_API
#define DLL_API
#endif
主要是linux:
args… 对应 ##args // QT会提示这种表示是GNU扩展
windows:
… 对应 ##__VA_ARGS__
// linux下:
#define Info(logFormat, args...) Info(__FUNCTION__, __LINE__, logFormat, ##args)
// windows下:
#define Info(logFormat, ...) Info(__FUNCTION__, __LINE__, logFormat, ##__VA_ARGS__)
参考:
发现有的函数是windows平台的。sprint_s是windows平台下线程安全的格式化字符串函数并非标准C函数,因此linux下无法使用,但可以使用snprintf函数代替。
int snprintf(char *dest, size_t n, const char *fmt, ...);
// 函数原型相同,替换即可
#define sprintf_s snprintf
windows下通过__declspec(dllexport)来声明DLL动态库导出的接口(函数或类),__declspec(dllimport)来声明为动态库加载的接口。linux下不可用。
linux下,GCC帮助文档 -fvisibility=default|internal|hidden|protected 参数下有这么一段话:
总结是:
查看文件属性:
查看导出函数:
Linux提供4个库函数、一个头文件dlfcn.h以及两个共享库()支持动态链接。
使用linux的库,使用方法和windows下一致。
#include <iostream>
#include <dlfcn.h>
#include "TceLogger.h"
using namespace std;
using namespace tce;
// declare function pointer
typedef TceLogger& (*type_pSo_TLGI)(void);
int main()
{
// dynamic load .so
// declare a void* handle (in windows HINSTANCE)
void *pSo_handle;
// use dlopen to load .so (in windows LoadLibrary)
pSo_handle = dlopen("../qtProject/libTceLogger.so", RTLD_NOW | RTLD_DEEPBIND);
if (!pSo_handle)
{
cout<<"can't open .so"<<endl;
cout<<"dlopen - "<<dlerror()<<endl;
return -1;
}
// use dlsym to get function address (in windows GetProcAddress)
type_pSo_TLGI pSo_TLGI = (type_pSo_TLGI)dlsym(pSo_handle,"TceLoggerGetInstance");
if (!pSo_TLGI)
{
cout<<"can't cast function"<<endl;
return -1;
}
// use function to get instance
TceLogger& logger = pSo_TLGI();
logger.Info("ok");
return 0;
}
动态加载时,需要使用dl库,在cmakelist中添加链接dl库。
cmake_minimum_required(VERSION 2.8)
project(SoCaller)
// 设置debug模式
SET(CMAKE_BUILD_TYPE DEBUG)
//设置C++11
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
// qt工程中显示h文件
FILE(GLOB_RECURSE LibFiles "TceLogger.h")
add_custom_target(headers SOURCES ${LibFiles})
// 设置include目录
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
// 设置库目录
link_directories(${CMAKE_CURRENT_SOURCE_DIR})
// 设置生成内容
add_executable(${PROJECT_NAME} "SoCaller.cpp")
// 设置要链接的库
target_link_libraries(${PROJECT_NAME}
dl
TceLogger //当静态加载时直接链接
)
参考:
在cmakelist中设置链接该动态库后,并包含头文件,可以直接使用。
// 使用动态库导出的C接口函数获取实例
TceLogger& tceLogger = TceLoggerGetInstance();
tceLogger.Crit("ok");
return 0;
在cmakelist中添加SET(CMAKE_BUILD_TYPE DEBUG)
在用测试demo debug时发现,,原来是生成so时,链接的log4cpp库没有后缀:
TARGET_LINK_LIBRARIES(${PROJECT_NAME} log4cpp)
,修改为
TARGET_LINK_LIBRARIES(${PROJECT_NAME} log4cpp.a)
修改链接log4cpp.a静态库后,报错relocation R_X86__32 against `.rodata’ can not be used when making a shared object。
原因是如果将编译的静态库链接进动态库使用,也就是我的应用情景,需要在编译静态库时,加上编译指令 -fPIC 。
因此在log4cpp源码的cmakelist中,增加指令:
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
然后不使用configure,直接cmake make,生成静态库,解决。
参考:
cmakelist 编写规则:
应该是没有链接pthread库,在log4cpp的cmakelist中,以及使用log4cpp.a的包装类中,添加链接pthread:
TARGET_LINK_LIBRARIES(${LOG4CPP_LIBRARY_NAME} pthread)
解决问题。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- awee.cn 版权所有 湘ICP备2023022495号-5
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务