2011-09-23 77 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