今天因为项目原因需要将ubuntu下的工程移植到windows平台。在ubuntu下面我们使用的是qmake来构建的工程,在windows上面移植的时候,将工程构建软件替换为cmake。
在移植的时候,也在吐槽windows的版本管理,什么vs2013的库不能用于vs2015编译链接,debug版本不能链接release版本之类的设定。我反正觉得这些设定挺奇葩的,在实际情况中,我们常常需要链接一些第三方库,如果是外部人员提供的话,那么就会只有release版本,调试起来就很难受了。
在移植成功后遇到了一个问题,这个问题折腾了我还比较久的时间。就是在我们工程中自己编写的动态库dll中需要导出类。而在我们类是用单例做成的。所以要导出的类中有一个静态成员变量。在主程序链接的时候一直报错,没有找到该静态变量。
代码结构类似这样:
dll h文件
#pragma once #include "stdio.h" #ifdef _DLL_INNER #define _EXPORT _declspec(dllexport) #else #define _EXPORT _declspec(dllexport) //#define _EXPORT _declspec(dllimport) #endif class _EXPORT ss { public: static ss * Ins() { if (m_ss) { } else { m_ss = new ss; } printf("addr :%x\n", m_ss); return m_ss; } private: static ss * m_ss; int aal; };
dll cpp文件类似这种
#define _DLL_INNER #include "defs.h" #include "stdio.h" ss * ss::m_ss=0;
主程序 cpp类似这种
#include "defs.h" #include "stdio.h" int main(int argc, char * argv[]) { ss *a = ss::Ins(); printf("addr: %x\n",a); getchar(); }
在这种情况下编译vs2015给我报了
错误 LNK2001 无法解析的外部符号 "private: static class ss * ss::m_ss" (?m_ss@ss@@0PEAV1@EA) teststatic c:\Users\zheng\documents\visual studio 2015\Projects\teststatic\teststatic\teSt.obj 1
针对于此问题,我能想到的是dll数据段和主程序数据段不通用。于是乎想弄dll共享的数据段,结果也没有解决这个问题。还有关于导出符号
#define _EXPORT _declspec(dllexport) #define _EXPORT _declspec(dllimport)
正反也测试了好多次,也是没有解决这个问题。后来无意间将 dll的文件结构改成如下所示,问题才得以解决:
dll h文件
#pragma once #include "stdio.h" #ifdef _DLL_INNER #define _EXPORT _declspec(dllexport) #else #define _EXPORT _declspec(dllexport) //#define _EXPORT _declspec(dllimport) #endif class _EXPORT ss { public: static ss * Ins(); private: static ss * m_ss; int aal; };
dll cpp文件:
#pragma once #include "stdio.h" #ifdef _DLL_INNER #define _EXPORT _declspec(dllexport) #else #define _EXPORT _declspec(dllexport) //#define _EXPORT _declspec(dllimport) #endif class _EXPORT ss { public: static ss * Ins(); private: static ss * m_ss; int aal; };
之后问题解决。
总结:函数实现还是放在cpp文件规范比较好。