最近在使用osg和qt开发,在集成osg时候因为我使用的qt版本为非opengl的版本,导致qt自己封了一遍opengl的一些基类变量如double 这时候就会跟osg中声明的opengl的类型冲突,提示重定义了不同的基类行。

解决方案:

使用opengl版本的qt库 =。。=

在QT中使用C++编写的lib库 需要修改pro文件,主要问题是引用路径的问题

_pro_file_pwd 代表了工程文件当前目录

可以通过在qt creator 的帮助中 搜索 variables 来查看相关详细介绍,或者参考一下

http://my.oschina.net/jinzei/blog/100989?p=1

相信大家很多和我一样,用多了微软给的便利,用人家的就十分不习惯.于是就琢磨原来用到的功能现在要整顺手来,不然可让人怎么活啊! 本篇主要介绍实践使用,并非一篇完整教程,有待读者补充.^_^

我们原本在VS上有一个大工程sln,里面有lib,有dll有exe,甚至还混搭了C#.用起来一点不觉得水土不服.现在要用QT重整,并且需要处处考虑换个平台不要让我改东西.作为探路先锋,先挑了几个基础工程出来做实验:

↑当然,图中是已经成事之后了.想在qtcreator中弄一个工程集还真不是那么方便,我到处找过了,压根没有创建工程集的办法.纵使你可以一个pro一个pro的拖进去,最后也没法保存,下次打开还得重新一个一个pro的拖,没哪个傻蛋总这么干吧..所以首先就是要手动创建一个subdirs型的pro做为工程集,也就是上面看到的
**CloudBoard_win32.pro**(subdirs举例)

TEMPLATE = subdirs

SUBDIRS =\
raknet\
onetengine \
omisc \
testDebugShow onetengine.depends = raknet omisc
testDebugShow.depends = omisc
#CONFIG += ordered

关于这个pro的详细写法,感觉qt文档写的很细碎,反正我是没看明白.就着广大网友的例子才有了上面一段.TEMPLATE=subdirs这是固定写法,声明是做工程集目录的.SUBDIRS是指明目录中有哪些项,可以嵌套另一个subdirs型的pro. 接下来可以详细定义其中的项目.如.depends表示左边的依赖=后面的项目.

.subdir
指定子项的目录,不使用子项本身的名字.

.file
明确指定该子项使用的pro文件,默认是根据名字自动找的,该项不和.subdir同时使用

.condition
Specifies a bld.inf define that must be true for subproject to be built. Available only on Symbian platform.

.depends
该子项依赖指定的子项,只在使用makefiles的平台有效

.makefile
该子项的makefile,只在使用makefiles的平台有效

.target
该子项的TARGET,只在使用makefiles的平台有效

以上翻译可能有问题.重新总结一下.使用subdirs =a b c d声明的其实是4个子项的名字.默认你不多做说明的话,qmake根据名字自动去找子目录,启用子目录中的pro文件(名字优先匹配).如果你特别说明a.subdir=./z或者a.file=./z/z.pro就可以不受名字限制. 至于.makefile,应该是你混用第三方库的时候才有必要手动指定使用的makefile. target可以在子pro中指定,除非你觉得这里比较统一方便修改.其余的未实践不多说.

**omisc.pro**(staticlib举例)

QT       -= gui   ①

TARGET = misc   ②
TEMPLATE = lib #固定写法
CONFIG += staticlib #静态库固定写法
#DEFINES += ③
DESTDIR = $$_PRO_FILE_PWD_/../lib ④
SOURCES += \
ostatic.cpp \
odebugoutput.cpp HEADERS += omisc.h \
ostatic.h \
ostringmap.hpp \
odebugoutput.h
unix:!symbian { ⑤
maemo5 {
target.path = /opt/usr/lib
} else {
target.path = /usr/lib
}
INSTALLS += target
}

①"QT"是使用的QT库,从平时向导创建工程可以看出,QT默认是包含gui和core,如果你不用,他自动生成的就是
QT-=core gui.此处QT-=gui表示我们还用了core
②TARGET是生成目标,名字不做修饰(不加.a/.lib/.dll)的好处是让qt帮我们加,在不同平台不用我们考虑差别.
同时这里的名字是可以前置路径的,如../lib/misc.它会生成在相对生成目录上一级的lib下.不过我劝你还是不要写相对路径了,因为在windows下会多出debug/release目录,目录深度不同,你换一个平台得重写.这还有更好的办法,后面继续.
③DEFINES是VS里面的预定义头,就是定义宏,哎哟总算见着熟人了~
④DESTDIR就是刚才②说的好办法.它控制最终的输出,相当于VS的OurDir.此处我们控制它输出到$$_PRO_FILE_PWD_/../lib.前面$$开头的是一个pro变量 ,存放的是工程路径,就是CloudBoard_win32.pro的路径,还有更多的定义参考Qt助手. 你可以用类似message($$_PRO_FILE_)的语句测试变量到底是什么值.具体使用是:写在pro中,右键pro的工程执行qmake.从编译输出中可以看到.

⑤最后这段是自动产生的,本人实在没有仔细研究,看样子应该是一种指定target目录的办法.而unix:!symbian让人不难想到,这是在筛选特定平台.具体的欢迎您测试后补充^_^

raknet相信很多童鞋了解,本案简单将其代码编译成staticlib,DESTDIR=$$_PRO_FILE_PWD_/../lib完工

**onetengine.pro**(动态库举例)

!include( ../common.pri ) {  ①
error(" Couldn't find the common.pri file! ")
} QT -= gui
QT += network xml TARGET = netengine
TEMPLATE = lib
DESTDIR = ../bin #基于生成目录 INCLUDEPATH += ../omisc ../raknet/source ②
DEPENDPATH += ../omisc ../raknet/source #基于工程目录
win32:LIBS += -lWs2_32 ③
LIBS += -lmisc -lraknet DEFINES += ONETENGINE_LIBRARY ④ SOURCES += onetengine.cpp \
netengine_export.cpp HEADERS += onetengine.h\
onetengine_global.h \
../include/macrodefine.h \
../interface/isinkfornetengine.h \
../interface/inetengine.h

**common.pri**(pro包含举例)

INCLUDEPATH += ../interface ../include  ⑤
#LIBS += -L$$QTDIR/lib
LIBS += -L../../src/lib
LIBS += -L../lib

①没错,pro中也是可以include的,以当前文件为起点将上一层的common.pri包含进来.common.pri中的相对路径依然以当前pro路径为基础.
②INCLUDEPATH是包含目录,类似于VS中的附加包含目录.至于 DEPENDPATH本人实事求是没有研究不明白有什么用.欢迎补充^_^

③使用筛选器,仅在win32下增加Ws2_32.lib的导入. LIBS相当于VS中的附加依赖库,不同的是可以通过-L指定库目录,-l指定库名.其间没有空格的哦.例如上面的LIBS+=-L../lib -lmisc就是可以到../lib中找misc库.misc没有说明.a还是.lib是让qt帮我们做.你也可以指定.lib,然后通过筛选器把其他平台的也写一下.
④提供宏定义ONETENGINE_LIBRARY是因为在向导创建动态库的时候qtcreator帮我们定义了这样的

#ifndef ONETENGINE_GLOBAL_H

#define ONETENGINE_GLOBAL_H

#include <QtCore/qglobal.h>

#if defined(ONETENGINE_LIBRARY)

#  define ONETENGINESHARED_EXPORT Q_DECL_EXPORT

#else

#  define ONETENGINESHARED_EXPORT Q_DECL_IMPORT

#endif

#endif // ONETENGINE_GLOBAL_H

提供宏定义ONETENGINE_LIBRARY决定了该工程的作用是导出动态库的.
⑤最后common.pri只是定义了几项公共的没有平台差异的信息

好了,testDebugShow的工程pro就不多说了,它和动态库的很相似,只有TEMPLATE=app没有XXXX_LIBRARY的宏定义而已.

最后补充一点,为什么总的工程名要叫CloudBoard_win32呢,明眼人一看就知道这是要分平台了呢.没错,一开始我也觉得一个pro就搞定了,里面可以有筛选器,一份pro足以应付.但是实际是qtcreator会为pro产生同名的.user文件,qtcreator的一些配置会写在.user里面,例如最关键的qtSDK位置,编译工具,构建/生成设置等.这些必须根据生成所处的环境区别设置. 所以当你原样跑到Linux下,启动pro就会告诉你配置是别处读来的,是否使用?是:配置一定是错的,否:配置被清洗.这都不是我们希望的.所以唯有分平台建总pro了.

QT 编译遇到重定义;不同的基类型&在QT中使用C++ lib库的更多相关文章

  1. C++纯虚函数、虚函数、实函数、抽象类,重载、重写、重定义

    首先,面向对象程序设计(object-oriented programming)的核心思想是数据抽象.继承.动态绑定.通过数据抽象,可以使类的接口与实现分离,使用继承,可以更容易地定义与其他类相似但不 ...

  2. "struct"类型重定义解决办法

    #ifndef 在头文件中的作用 在一个大的软件工程里面,可能会有多个文件同时包含一个头文件,当这些文件编译链接成一个可执行文件时,就会出现大量 “重定义”的错误. 在头文件中使用#ifndef #d ...

  3. 在线重定义(Rdefine Table online)

    二.        概念理解 在线重定义用于对表的逻辑或者物理结构的修改,而且在修改时不影响表的可用性与传统方式相比.当一个表被重定义时,会被锁定为exclusive mode很短一段时间,这段时间的 ...

  4. C++ 学习笔记 (八)重载 重写 重定义以及名字覆盖

    学习C++必定会遇到重载.重写.重定义.概念的东西多也是学习C++蛋疼之处,但是还是得弄懂,学懂了也就不觉得多了. 概念,特点: 重载: 直白点说就是函数名字相同,传参的个数,类型不一样.判断标准在于 ...

  5. “sockaddr”: “struct”类型重定义的错误的解决办法《转》

    原帖地址:https://blog.csdn.net/clever101/article/details/100163301 windows.h和winsock2.h存在有类型重定义,往往体现在VC程 ...

  6. c++继承关系中成员函数的重载、重写、重定义之间的区别

    1.Override.Overload.Redefine Overload 重载只能发生在类内部,不能发生在子类和父类的继承中.具体来说,如果子类中有父类同名.同返回值类型,但是不同参数列表,这两个在 ...

  7. C++编译错误--C++连接redis:编译错误error C2371: “off_t”: 重定义;不同的基类型

    编译错误:对于编译C++调用hiredis编译错误:error C2371: “off_t”: 重定义:不同的基类型,如下图: 可能的解决方案: 1. 因为hiredis预处理器定义了_OFF_T_D ...

  8. C++中重定义的问题——问题的实质是声明和定义的关系以及分离式编译的原理

    这里的问题实质是我们在头文件中直接定义全局变量或者函数,却分别在主函数和对应的cpp文件中包含了两次,于是在编译的时候这个变量或者函数被定义了两次,问题就出现了,因此,我们应该形成一种编码风格,即: ...

  9. 海思编译链编译出现__aeabi_unwind_cpp_pr1重定义怎么回事

    1.用arm-hisiv100nptl-linux-gcc编译代码,结果发现报错,__aeabi_unwind_cpp_pr1重定义,在librt.a先定义,使用的海思芯片是hi3520d. 2.本来 ...

随机推荐

  1. vue中nextTick的使用(转载)

    转载自:https://www.cnblogs.com/chaoyuehedy/p/8985425.html 简介 vue是非常流行的框架,他结合了angular和react的优点,从而形成了一个轻量 ...

  2. DES加密之强制更新下载分离器

    数据加密算法(Data Encryption Algorithm,DEA)是一种对称加密算法,很可能是使用最广泛的密钥系统,特别是在保护金融数据的安全中,最初开发的DEA是嵌入硬件中的.通常,自动取款 ...

  3. 02-oracle字符函数

    字符函数(scott/tiger 登陆) --upper(col name)将字符大写 --lower(col name)将字符小写 --initcap(col name)字符串的首字母大写,其余小写 ...

  4. signed char型内存位bit表示

    signed char型内存 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9 ...

  5. centos 7编译安装nginx

    一.安装nginx时必须先安装相应的编译工具yum -y install gcc gcc-c++ autoconf automakeyum -y install zlib zlib-devel ope ...

  6. django notes 三:Template 的查找

    django 中有 2种 Template Loader django.template.loaders.filesystem.Loader django.template.loaders.app_d ...

  7. 在Eclipse添加Android兼容包( v4、v7 appcompat )[转]

    昨天添加Android兼容包,碰到了很多问题,在这里记录一下,让后面的路好走. 如何选择兼容包, 请参考Android Support Library Features(二) 一.下载Support ...

  8. Android ListView分组显示

    ListView的实现方法也是普通的实现方法.只不过在list列表中加入groupkey信息.在渲染的时候要判断是否是分组的标题. 就是在使用不同的两个View的时候存在这种情况,convertVie ...

  9. linux diff(differential) 命令

    功能说明:比较文件的差异. 语法:diff [OPTION]... FILES 实例: diff -ur temp1 temp2 diff -ur temp1 temp2 > temp.diff ...

  10. Vue路由开启keep-alive时的注意点

    Vue路由开启keep-alive时的注意点   这个不是业务的要求,但是看到每次进入页面就重新渲染DOM然后再获取数据更新DOM,觉得作为一个前端工程师有必要优化下的加载逻辑,正好vue提供了 ke ...