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

解决方案 »

  1.   

    初步判断其实是VS2008编译器过敏,在EXE工程里面无需给出DLL头文件写法的警告,它没导出链接肯定出错误,实际上那个宏在DLL工程里面是定义成__declspec(dllexport)的,已经导出来,但是EXE里被定义成空,它多此一举的警告没有导出。但是在EXE里写__declspec(dllexport)居然反倒没有警告,你EXE里只不过是导入,你管导出的事干什么?
      

  2.   

    在使用 DLL_EXPORT 的时候,表示该符号是导出的。
    在使用这些到处函数的时候,不明确要求使用 DLL_IMPORT。
    如果没有使用 __declspec(dllimport) ,那么该函数将直接调用。
    否者,编译器会添加一个函数包装。
    使用 __declspec(dllimport) 和不使用的差别就在于一个函数包装。
    所以建议使用 __declspec(dllimport) 来使用导入符号。 
      

  3.   

    问题是这是模板类和函数,如果exe里直接使用这个模板,代码肯定是在exe里,不存在你说的那个问题。感觉还是编译器对模板支持的不全。导出符号的意义是告诉编译器,这些函数和类可能供别人调用,所以lib里写上这些入口。
    导入符号的意义是告诉编译器,这函数和类或者对象是在其他模块中,链接的时候会有优化。但是模板只有在使用的时候才生成代码,如果一个dll中的类使用了一个模板类作为成员,这个模板类就必须导出,这个时候,代码是在dll中的。如果在exe中直接使用这个模板,就不能导入,因为代码是在exe本地。也就是说必须识别,这个模板对象是在dll中还是本地,这两种情况是不同的,一个需要导入,一般必须不能导入。