2011-09-23 36 views
1

我试图用​​来调用一个c函数,该函数作为另一个函数的指针返回。从文档看来,我可以通过使用CFUNCTYPE声明函数,然后使用指针创建一个实例来完成此操作。但是,这似乎给了我一个段错误。这里是一些示例代码。调用函数作为指针从ctypes中的其他函数返回

sample.c文件:

#include <stdio.h> 

unsigned long long simple(void *ptr) 
{ 
    printf("pointer = %p\n", ptr); 
    return (unsigned long long)ptr; 
} 

void *foo() 
{ 
    return (void *)simple; 
} 

unsigned long long (*bar)(void *ptr) = simple; 

int main() 
{ 
    bar(foo()); 
    simple(foo()); 
} 

和simple.py:

from ctypes import * 
import pdb 

_lib = cdll.LoadLibrary('./simple.so') 

_simple = _lib.simple 
_simple.restype = c_longlong 
_simple.argtypes = [ c_void_p ] 

_foo = _lib.foo 
_bar = CFUNCTYPE(c_int, c_void_p)(_foo()) 

pdb.set_trace() 
_bar(_foo()) 

这里有一个GDB/PDB会议:

(gdb) r 
The program being debugged has been started already. 
Start it from the beginning? (y or n) y 
Starting program: /usr/bin/python simple.py 
[Thread debugging using libthread_db enabled] 
> .../simple.py(15)<module>() 
-> _bar(_foo()) 
(Pdb) p _foo() 
-161909044 
(Pdb) cast(_bar,c_void_p).value 
18446744073547642572L 
(Pdb) _simple(_foo()) 
pointer = 0xfffffffff65976cc 
-161909044 
(Pdb) int('fffffffff65976cc',16) 
18446744073547642572L 

奇怪的是,如果我运行使用C主功能,我得到

$ ./simple 
pointer = 0x400524 
pointer = 0x400524 

它与我从python代码中获得的指针不匹配。

我在这里做错了什么?

在此先感谢您提供的任何指导!

+0

我觉得指针可以不同于电话呼叫,或至少指针取决于方法被调用的环境。 – rocksportrocker

回答

2

您还没有定义任何_foo返回类型,尝试添加:

_foo.restype = c_void_p 

ctypes的默认为int的返回类型,并且它看起来(从PDB你做会投)好像你是在64-这意味着您的指针在转换为int时将被截断。在我的系统上,代码似乎可行 - 但这是一个32位系统(不幸的是,我现在没有任何可用的64位系统可供测试)。

你也_bar定义并没有真正匹配的是在C代码,我建议使用类似:

_bar = CFUNCTYPE(c_longlong, c_void_p).in_dll(_lib, "bar") 
+0

非常感谢您的回复。你说得对,'_foo.restype'声明是这里的问题。这实际上是一个问题的缩合,我仍然有一些更复杂的代码(这就是为什么我按照我的方式分配'_bar',而不是使用'in_dll'),所以我试图找出什么那是。当我想到如何重现我实际存在的错误时,我会回来,如果我想出解决方案,我会回来:)再次感谢! – user961826