显示标签为“python”的博文。显示所有博文
显示标签为“python”的博文。显示所有博文

2013年4月11日星期四

为什么64位下用python调用C库发生了崩溃

在64位下,把一些库封装成C函数,然后编译成so文件供python调用,结果发生了崩溃。
今天试验后发现:如果C函数返回void*等类型,把返回值赋值到python变量后被截断,只剩下低32位的值。
因此,如果C函数中的指针在0xffffffff以上的地址的时候,返回到python中就会被截断。如果再继续使用这个被截断后的地址值,就会发生崩溃。

下面是模拟崩溃的代码:
//C
void* create_object()
{
    return new int(0);
}

void free_object(void* obj)
{
    delete (int*)obj;
}

#python中这样调用
so = cdll.LoadLibrary('xxxx.so')
obj = so.create_object()  #这里被截断
so.free_object(obj)       #这里发生崩溃

=====================================================
解决办法也比较简单,不要通过返回值传递指针,而通过指针参数返回:

void create_object(uint64_t* out)
{
    *out = (uint64_t)new int(0);
}

void free_object(void* obj)
{
    delete (int*)obj;
}



#python中这样调用
so = cdll.LoadLibrary('xxxx.so')
obj = ctypes.c_ulonglong(0)
so.create_object(ctypes.byref(obj))
obj = ctypes.c_void_p(obj.value)
so.free_object(obj)


这里要注意:发现python中的对象的地址都在0xffffffff之内,所以使用byref没发现问题。
byref是否会截断指针,这个还没试验出来。

2012年11月28日星期三

python: 转换被错误定义为unicode类型的utf-8编码

某同事的代码中发现,本来是utf-8编码的字符串,从数据库读出来后,被错误返回为u'utf-8内码'这样的格式。

下面是一个简单的转换方法,还原其为正常的utf-8编码:

>>> a = '测试'
>>> a
'\xb2\xe2\xca\xd4'
>>> b = a.decode('gbk').encode('utf-8')
>>> b
'\xe6\xb5\x8b\xe8\xaf\x95'
>>> c = u'\xe6\xb5\x8b\xe8\xaf\x95'
>>> c
u'\xe6\xb5\x8b\xe8\xaf\x95'
>>> arr = array.array('B')
>>> arr.fromlist([ord(i) for i in c])
>>> print arr.tostring().decode('utf-8').encode('gbk')
测试 

最终的代码是这样:
import string
import array
s = u' \xe6\xb5\x8b\xe8\xaf\x95 '
arr = array.array('B')
arr.fromlist([ord(i) for i in s])
print arr.tostring().decode('utf-8').encode('gbk')

如果读者知道更好的转换方法,希望不吝赐教。

2012年11月27日星期二

安装python图标库pycha搞得很郁闷

根据帖子推荐,发现pycha是所有python图标库中比较简单的,于是打算采用这个。
结果,安装这个库花了我两个半天,仍未能解决,打算放弃。

1. 首先在pycha的首页https://bitbucket.org/lgs/pycha/wiki/Home找下载地址。
   找了半天居然没有,只有个项目管理软件hg的地址。
   好吧,先安装windows下的hg客户端。
2. 安装hg客户端:
  http://cdn.bitbucket.org/tortoisehg/files/downloads/tortoisehg-2.6.0-hg-2.4-x86.msi
3. 使用hg下载源码:
  hg clone http://bitbucket.org/lgs/pycha
4. 安装上了没效果,原来还需要库 cairo。于是下载cairo
  http://www.cairographics.org/releases/py2cairo-1.10.0.tar.bz2
5. cairo库不同于一般python库的安装,居然还需要python的头文件,于是再下载python源码包来编译:
    http://www.python.org/ftp/python/2.7/Python-2.7.tgz
6. 再编译cairo,指定头文件的路径,仍然编译不通过……

选择一个不成熟的库,果然很折腾啊!





2012年9月14日星期五

python PIL: 图片的倒影效果的简单实现

具体的算法就是把图片的每一行对称翻转,然后将透明度从低到高逐行设置。
见代码:


import sys,os
from PIL import Image

if __name__=='__main__':
    argc = len(sys.argv)
    if argc<3:
        print 'usage:%s <file> <dest>'%sys.argv[0]
        sys.exit(-1)
    im = Image.open(sys.argv[1]).convert('RGBA')
    arr = []
    (w,h) = im.size
    x = 0
    y = 0
    index = 0
    arr_row = []
    for pixel in im.getdata():
        pixel = list(pixel)
        x = index % w
        y = index / w
        index += 1
        pixel[3] = int(256.0*0.2*(float(y)/float(h)))
        arr_row.append(tuple(pixel))
        if index%w==0 and index>0:
            arr = arr_row + arr
            arr_row = []
    #
    im1 = Image.new('RGBA', (w,h))
    im1.putdata(arr)
    im1.save(sys.argv[2])

原图和效果见下面:


2012年8月30日星期四

小记:python中用PIL进行图形合成

网站上需要展示一个类似如下的图:

整个图包含了三部分:背景,带透明度设置的阴影,以及封面。三个图通过程序合成成以上的样子。

用PIL实现极为简单,但摸索了差不多半小时才搞好,贴出来,或许对某人有用:


bg = Image.open(r'F:\temp\bg.png').convert('RGBA')
shadow = Image.open(r'F:\temp\shadow.png').convert('RGBA')
cover = Image.open(r'F:\temp\cover.png').convert('RGBA')
#下面这步是关键,蒙版的对象,采用自身即可根据透明度进行运算
bg.paste(shadow, ((bg.size[0]-shadow.size[0])/2,(bg.size[1]-shadow.size[1])/2), shadow)
bg.paste(book, ((bg.size[0]-book.size[0])/2,(bg.size[1]-book.size[1])/2))
bg.save(r'F:\temp\result.png', format='png')