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是否会截断指针,这个还没试验出来。

2013年4月1日星期一

linux64下的一个链接问题: crtbeginT.o

尝试链接一个动态库,结果crtbeginT.o这个系统库出现错误:


g++ -o ttc_api_c.o -c ttc_api_c.cpp -g -Wall -Werror -O2 -fPIC
g++ -o ttc_api_c.so -shared ttc_api_c.o libttc.pic_64.a -static
/usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/4.4.6/crtbeginT.o: relocation R_X86_64_32 against `__DTOR_END__' can not be used when making a shared object; recompile with -fPIC
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/crtbeginT.o: could not read symbols: Bad value
collect2: ld returned 1 exit status

百思不得其姐,还好搜索到这篇帖子:
https://bugs.launchpad.net/ubuntu/+source/gcc-4.4/+bug/640734

采用文中的办法,酱紫解决了:

cd /usr/lib/gcc/x86_64-redhat-linux/4.4.6
cp crtbeginT.o crtbeginT.orig.o
cp crtbeginS.o crtbeginT.o