calling functions returned as pointers from other functions in ctypes
I'm trying to use ctypes
to call a c function that was returned as a pointer from another function. It seems from the documentation that I can do this by declaring the function with CFUNCTYPE
, and then creating an instance using the pointer. This, however seems to give me a segfault. Here is some sample code.
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());
}
and 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())
Here's a gdb/pdb session:
(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
Curiously, if I run using the C main function, I get
$ ./simple
pointer = 0x400524
pointer = 0x400524
which doesn't match the pointer that I get from the python code.
What am I doing wrong here?
Thanks in advance for a开发者_JS百科ny guidance you can give!
You are not defining any return type for _foo, try adding:
_foo.restype = c_void_p
ctypes defaults to int returntype, and it looks (from the cast done in you pdb session) like you are on a 64-bit system meaning that you pointer will be truncated when converted to int. On my system the code seems to work - but that is a 32-bit system (and unfortunately I don't have any 64-bit system available to test on right now).
Also you _bar definition doesn't really match what is in the C code, I suggest using something like:
_bar = CFUNCTYPE(c_longlong, c_void_p).in_dll(_lib, "bar")
精彩评论