最近有时间学习OpenGL,于是买了本OpenGL编程指南第八版,看完第一章以后,对第一章中的例子进行了实现,之后遇到了一些问题,这里记录一下遇到的问题以及相对应的解决方法:
1、#include "vgl.h"以及 #include "LoadShaders.h"
看到这里的头文件,书中提到作者使用的是Freeglut以及glew的工具库,因而到网上把这两个工具库,分别引入项目中,然后发现仍然无法编译
这里是因为无法找到"vgl.h"以及"LoadShaders.h"这两个头文件,因而到网上把作者的源码下载下来了(http://opengl-redbook.com/)
然后C++包含目录包含include文件夹,C++库目录包含lib文件夹,并添加现有的cpp文件"LoadShaders.cpp"到工程里面,至此代码可以编译了
2、无法解析的外部符号 _sscanf,该符号在函数 _glutInit 中被引用
看到这里首先想到是以前遇到的一个报错:
'sscanf': This function or variable may be unsafe. Consider using sscanf_s instead
这里说明一下原因:"sscanf"这个函数是不会进行参数检测的,微软担心会造成内存异常,就改写了一个同样功能的函数"sscanf_s"使这些函数更加安全
很明显我们这里不希望使用"ssanf_s"
解决方法:
a、在预编译头文件"stdafx.h"中引入任何头文件之间加入
#define _CRT_SECURE_NO_DEPRECATE
b、使用
#pragma warning(disable:4996)
c、在C/C++ -> 预处理器 -> 预处理器定义中增加"_CRT_SECURE_NO_DEPRECATE"
以上的3个方法都只是屏蔽了警告,并没有使用新的函数进行替换
d、在预编译头文件"stdafx.h"中引入任何头文件之间加入
#define _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
这样在连接的时候,就会把旧函数替换成新函数
(来自参考:http://www.cnblogs.com/gb2013/archive/2013/03/05/SecurityEnhancementsInTheCRT.html)
但是使用上述的方法以后问题依然存在...
随后在翻看资料的时候注意到了"楼主的C4996变成了error,貌似是选中了“将警告视为错误”的编译选项或者在使用COM开发吧"
考虑到我们这里的确是在lib文件里用到的"scanf"可能是这个原因,因而调整思路重新搜索
a、拿到lib的源代码,然后在2015中重新编译(...这个在第八版的源码没有找到源码,不知道怎么重新编译)
b、连接器 -> 输入 -> 附加依赖项中添加"legacy_stdio_definitions.lib"
在这里也找到了出现这个问题的原因:
VS2015会使用内联的方式调用"stdio.h"文件的部分函数,因而我们的obj文件或者lib文件使用这些函数的时候,需要引入legacy_stdio_definitions.lib来提供一个可用的外部链接
(来自参考:http://bbs.csdn.net/topics/391839926 和 http://stackoverflow.com/questions/32418766/c-unresolved-external-symbol-sprintf-and-sscanf-in-visual-studio-2015)
3、无法解析的外部符号 ___iob_func,该符号在函数 _fgError 中被引用
搜索后发现问题的原因:VS2015中对___iob_func定义不一致导致的,而___iob_func的定义和stdin、stdout和stderr的定义相关,显然是lib使用了stderr之类引起的错误
好吧!到这里以后,这个问题很长时间无法得到解决,沿着这一条路无法在进行下去了...
看到"freeglut_static_vs2010_d.lib"恩,明显这个lib对应的是VS2010,因此想为什么不能找一个VS2015版本的呢
因而现在方向改变了,把上述对项目的修改全部清除掉,想办法找到VS2015生成的lib
4、使用VS2015生成Freeglut的lib文件以及glut的lib文件
准备工作安装CMake,下载Freeglut和glew
a、打开CMake的GUI然后把"Where is the source code?"指向文件夹中包含"CMakeLists.txt"的目录,例如:"glew-1.12.0\build\cmake"
b、把"Where to build the binaries"指向一个输出文件
c、点击Configure设置编译器
d、然后根据提示生成VS2015可用的项目文件
(以上参考: http://blog.csdn.net/zhuxiaoyang2000/article/details/49158965)
e、打开输出目录中的项目,修改常规 -> 配置类型 静态库(.lib)然后编译运行
(参考: http://blog.csdn.net/mafuli007/article/details/7320663)
5、好吧!问题总是就这么发生了
解决方法:
连接器 -> 命令行 输入"/SAFESEH:NO"
然后问题终于解决了,在刚刚项目的目录下的lib文件夹中找到了glew32d.lib...
依据上面生成glew的方法,对Freeglut也进行编译生成,此时所有的lib文件就都拿到手了,可是着手最上面的例子
恩,这里生成的lib文件的数目和源码中的lib文件数目不一致,而且不明白用途的情况下,也不敢随意的揣测他们之间的对应关系,想到作者的源码应该也是对Freeglut和glew的使用,因而直接在Freeglut和glew的基础上对项目进行编译
a、分别引入Freeglut和glew的"include文件夹"、”lib文件夹“
b、引入头文件和作者源码中实现的类和方法
#include <gl/glut.h> #include <gl/freeglut.h> #include "LoadShaders.h" #define BUFFER_OFFSET(x) ((const void*) (x))
6、发现所有的与glew相关的函数,都无法解析(?)
查看作者的vgl.h看到使用#pragma comment添加了一些lib文件,类比者添加了
#pragma comment (lib, "libglew32d.lib")
7、编译通过可是却在运行是崩溃了....
好吧,在刚刚的freeglut项目中找到了freeglutd.dll然后把它拷贝到"system文件夹"中
再次运行项目,至此例子到这里运行成功了
题主小白一只,为了运行这个例子,百度、google找资料不停得尝试,总算把例子给跑通了,这里把它记录下来,希望能对一些人有所帮助
ps:在这一系列解决问题的过程中,有很多时候,只是跟着blog等的解决步骤一步一步走下来的,很多地方完全不知道为什么?甚至很多地方根本不知道怎么提问?
这里收集了一些我在这个过程能想到的问题,希望有能力解决人,能够帮助我一下
1、上面第3个问题"无法解析的外部符号 ___iob_func"只能通过重新编译lib来解决吗?如果如此那么遇到不知道源码的情况下,这个问题怎么解决?
2、上面第6个问题,我明明已经把glew生成的lib文件都包含在库目录下面了,问什么还是提示无法解析,#pragma comment (lib, ".lib")和包含到库目录这两者
到底发挥着什么样的作用?