Qt的plugin机制其实就是dll,那可能会有疑问:plugin生成的dll在project中使用和正常的dll有什么区别?答案就是区别很大,plugin,顾名思义,插件可有可无,有插件(dll),我的软件可以正常运行;没有插件,我的软件应该也可以运行,只不过插件功能不能体现在我的软件中了;但是正常的dll是我的软件不可缺少的一部分,没有它,我的软件就不能打开。由此可见,plugin功能给应用程序提供了很灵活的功能扩展。废话少说,来看看怎么在Qt project中创建和使用吧! 要遵循以下步骤:
#define MikPlugin_IID "mihooke.github.io"
再声明这个接口类到Qt元系统中
Q_DECLARE_INTERFACE(MikPluginInterface, MikPlugin_IID)
Q_PLUGIN_METADATA(IID MikPlugin_IID FILE "mikPlugin.json")
Q_INTERFACES(MikPluginInterface)
注意:这里需要在代码目录下创建一个json文件,内容是key:value形式。一般为空就行。
QObject *object;
a.addLibraryPath(QString("../debug"));
QPluginLoader l(QString("MikPlugin")) ;
if ( (object=l.instance()) != NULL )
{
qDebug("plugin loaded .");
MikPluginInterface* plugin = qobject_cast<MikPluginInterface*>(object) ;
if (plugin)
plugin->hello("hello plugin");
}
else
{
qDebug("failed to load plugin !! ");
QString errorStr = l.errorString();
qDebug()<<errorStr;
}
可以用socket.error来捕获,通常我们捕获异常是利用send和recv函数来捕获,那么socket某一方的断开,也是通过send和recv来获知的,所以我们就可以从这里着手来处理。
可以这么使用:
try:
sock.send(1024)
except socket.error:
# reconnect
recv函数情况比较复杂,它处理异常分为两种情况:
recv_str = sock.recv(1024)
if len(recv_str) == 0:
# reconnect
Python官方文档对socket连接断开的描述
When Sockets Die
Probably the worst thing about using blocking sockets is what happens when the other side comes down hard (without doing a close). Your socket is likely to hang. TCP is a reliable protocol, and it will wait a long, long time before giving up on a connection. If you’re using threads, the entire thread is essentially dead. There’s not much you can do about it.
值得注意的是,当你写服务端程序时,在捕获异常进行reconnect时,千万记得把当前连接关闭
Python的property由两种用法: property函数形式:返回类的属性,类的方法由参数指定 property装饰器形式:由@property修饰类成员函数 这里暂不提property的实现,我们先来看看property的使用。为什么要用property?原因是由于Python中类的属性都是public的,即外部可以访问类的所有,即便你把变量声明为_a,__b,这只是一个约定俗成,告诉你这是类的私有变量,你不应该在外部去访问它们,但是你依然可以访问修改它们,有时候这是很方便直观的,但在有些时候,你需要对某些变量加一些约束,那么只好定义一些接口(getter和setter)来处理了。在C++中,这也是很正常很推荐的操作,通过接口来访问成员变量。但在Python中,这样会让程序员觉得多此一举,我明明可以直接访问成员变量,为啥还要访问接口呢? 这时候运用property就显得很有作用了,定义property后,你依然可以享受直接访问成员的便利,还可以自定义该成员变量的约束,下面用例子来说明用法。
property函数
class Mihooke(object):
def __init__(self):
self._daughter = None
def daughter_setter(self, d):
self._daughter = d
def daughter_getter(self):
return self._daughter
def daughter_grow_up(self):
del self._daughter
daughter = property(daughter_getter, daughter_setter, daughter_grow_up, "Mihooke has a daughter, Wow!")
我可以这么用:
m = Mihooke()
m.daughter = "LingYue" # invoke daughter_setter()
print(m.daughter) # invoke daughter_getter()
del m.daughter #invoke daughter_grow_up()
property()函数有4个参数:
property装饰器 装饰器则是修饰一个函数,这里使用property来修饰。
class Mihooke(object):
def __init__(self):
self._daughter = None
@property
def daughter(self):
return self._daughter
@daughter.setter
def daughter(self, d):
self._daughter = d
@daughter.deleter
def daughter(self):
del self._daughter
用法和上面相同。 注意:使用装饰器后,3个函数名字是相同的,函数名字就是属性的名字
后记:这个property特性很有用,在实际项目工程中,假设Mihooke类已经封装成一个模块了,这里的代码不能做修改,必须要在外部动态改变它的属性值,从而来获知这个改动,那么就可以用property来实现。同样的功能在Qt中也有体现,那就是Q_PROPERTY,这也是一个很有用的功能,之后的文章我会来剖析它。
Python代码里的注释有3种:
def f(x):
"This is a informal annotation"
return (x*x)
其实这里可以把双引号之间的当作无名的字符串。这里我们介绍如何去除上面三种注释。 一个思路是按照行遍历文件,遇到#,则删除#后面的字符;遇到”"”或’’‘,则进行计数,如果数量是奇数,说明只接下来遍历的行在注释之间,跳过继续遍历,如果数量是偶数,说明本段注释遍历完毕,对其删除。按照这个思路,下面是参考代码:
def deleteComment(file):
with open(file, 'r') as f:
lines = ""
three_double_quota_count = 0
three_single_quota_count = 0
all_context = f.readlines()
for i,line in enumerate(all_context):
if (i > len(all_context)-2):
break
idx = line.find("#")
if idx == 0:
continue
elif idx > 0:
line = line[:idx] + "\n"
idx_quota = line.find(r'"""')
if idx_quota >= 0:
three_double_quota_count += 1
continue
else:
if three_double_quota_count % 2 == 1:
continue
idx_quota = line.find(r"'''")
if idx_quota >= 0:
three_single_quota_count += 1
continue
else:
if three_single_quota_count % 2 == 1:
continue
lines += line
通常在Python中处理字典是这么写的:
dic = {}
try:
print(dic["key1"])
except KeyError:
print("key1 not exists")
在字典元素不确定的时候要写很多try except块,对程序阅读很不直观,如果我们不想对KeyError当作异常处理,只是想在键不存在的时候赋一个默认值,这可怎么办呢? 字典有一个方法get(),可以这么做:
dic = {}
print(dic.get("key1", "value1"))
我们都知道编译器在编译程序阶段都会对程序进行合法性的检查,如果不合法则会报出error信息,导致编译不能通过;同时也会进行合理性检查,如果某些语句不合理,则会报出warning信息,通常warning不影响编译生成汇编代码和可执行文件,但是warning信息通常都是友好的,出现warning,一般是代码中有潜在的问题,下面是常见的warning:
通常我们在编译项目的时候,都会把警告等级调到最高,比如在vs2015下

会选中启用所有警告,同样在Qt Creator下的pro文件中,我们也会加上 /Wall来开启最高等级警告,目的就是为了防止由于失误导致的隐藏性错误。 截至到这一步,所有操作都是正确的,并且是推荐的做法,直到某一天,我们的项目,需要引入第三方库,比如Boost,Eigen等等,写好程序,再次编译程序你会发现信息栏会输出一大堆的warning信息,特别是有符号数和无符号数不匹配,但是我们也不能去修改第三方库啊,指不定会出现什么样的奇怪的错误导致编译错误呢。既想关掉第三方库的警告信息,但是需要在自己的项目中继续启用所有警告,那怎么办? 有一个办法:创建一个头文件,这个头文件包含第三方库的头文件,并在这个头文件中选择性地关闭某些warning,项目中统统include这个头文件,下面是个示例: 比如第三方库头文件eigen/eigen.h
新建my_eigen.h
#pragma warning(push) // 仅禁用此头文件
#pragma warning(disable:4100) // 4100就是未使用函数参数
#include "eigen/eigen.h"
#pragma warning(pop) // 恢复最初的warning级别
再次编译,会发现整个世界都清静了!