最简单的情况,如果一个单纯的模板或者和模板函数,是不需要导出符号的,无论是DLL还是使用这个DLL的工程,编译链接都不会有警告。因为代码实际上是在使用DLL的工程里面,而不是DLL里面,所以其实和静态库没有本质区别。但是当你在DLL中也使用了那个模板函数和模板类,情形就不同了,那些代码是在DLL中的,此时如果你使用这个DLL的工程就会有警告,让你把那些模板类导出。那就加个导出符号吧。但是问题又来了,编译警告没有了,链接错误出现了,因为EXE工程里面使用这个模板类的代码实际上是在EXE里面的,import会导致找不到这个函数定义。再使用宏定义大法,把DLL里的定义写成export,在EXE里把这个导出符号定义成空,程序运行正常但是,还是有编译警告,说需要留出dll接口,这个警告是在EXE里的,DLL里没有。情况发生在一个非模板类使用了一个模板成员的情形。import也不行,空也不行,干脆改成export,这样在DLL和EXE里,模板类实际上都是__declspec(dllexport),这回一切正常了,没有编译警告,没有错误,程序运行正常。问题目前解决了,但是好像没有看过这方面的资料,DLL里的模板类和模板函数定义,并且DLL本身(含模板和非模板代码)也使用了这些类、函数的情况,一般是怎么处理的,有有这方面经验的吗?
在使用这些到处函数的时候,不明确要求使用 DLL_IMPORT。
如果没有使用 __declspec(dllimport) ,那么该函数将直接调用。
否者,编译器会添加一个函数包装。
使用 __declspec(dllimport) 和不使用的差别就在于一个函数包装。
所以建议使用 __declspec(dllimport) 来使用导入符号。
导入符号的意义是告诉编译器,这函数和类或者对象是在其他模块中,链接的时候会有优化。但是模板只有在使用的时候才生成代码,如果一个dll中的类使用了一个模板类作为成员,这个模板类就必须导出,这个时候,代码是在dll中的。如果在exe中直接使用这个模板,就不能导入,因为代码是在exe本地。也就是说必须识别,这个模板对象是在dll中还是本地,这两种情况是不同的,一个需要导入,一般必须不能导入。