Hi,
I have a segfault problem with ctypes. Script attached.
I simply need to call `libgio.g_file_new_for_path` and then
`libgio.g_file_get_uri` with its result. That result is a GFile*. Since I
don't manipulate that GFile* I don't think I have to mess with argtypes &
restype of the functions. I still tried ctypes.c_uint and ctypes.c_void_p.
In all cases after a few iterations g_file_get_uri will segfault. This does
not happen in the native version.
You will find python & c script attached.
Here is the result of a typical run:
$ LANG=C python2 ctypes_gio.py
Step 0
getting g_file_ptr for /foo/bar
getting uri_ptr with 8093280
free g_file_ptr
getting uri
free uri_ptr
Step 1
getting g_file_ptr for /foo/bar
getting uri_ptr with 8093344
free g_file_ptr
getting uri
free uri_ptr
Step 2
getting g_file_ptr for /foo/bar
getting uri_ptr with 8093824
free g_file_ptr
getting uri
free uri_ptr
Step 3
getting g_file_ptr for /foo/bar
getting uri_ptr with 8093440
free g_file_ptr
getting uri
free uri_ptr
Step 4
getting g_file_ptr for /foo/bar
getting uri_ptr with 8093472
free g_file_ptr
getting uri
free uri_ptr
Step 5
getting g_file_ptr for /foo/bar
getting uri_ptr with 8093856
free g_file_ptr
getting uri
free uri_ptr
Step 6
getting g_file_ptr for /foo/bar
getting uri_ptr with 140176928020160
free g_file_ptr
Erreur de segmentation (core dumped)
As you can see segfault happens as soon as the pointer position is outside
[0, 2^31[.
This is why I tried messing with argument/response types.
What am I doing wrong? Any pointer (ahah) on how to solve my problem?
The c code can be compiled that way:
$ gcc $(pkg-config --cflags gio-2.0) segfault.c -o segfault $(pkg-config
--libs gio-2.0)
Thanks
Bruno
import ctypes
import ctypes.util
class GioURI(object):
"""Use gio URI function g_file_get_uri. Paths must be utf-8 encoded.
"""
name = "GIO"
def __init__(self):
self.libgio = self.get_library()
self.available = bool(self.libgio)
def get_library(self):
lib_name = ctypes.util.find_library("gio-2")
try:
return ctypes.cdll.LoadLibrary(lib_name)
except OSError:
return False
def uri(self, path):
print(b"getting g_file_ptr for %s" % path)
self.libgio.g_file_new_for_path.restype = ctypes.c_void_p
g_file_ptr = self.libgio.g_file_new_for_path(path)
if not g_file_ptr:
raise RuntimeError("No gfile pointer received for {0!r}".format(
path))
try:
print("getting uri_ptr with %s" % g_file_ptr)
uri_ptr = self.libgio.g_file_get_uri.argtypes = [ctypes.c_void_p]
uri_ptr = self.libgio.g_file_get_uri(g_file_ptr)
except:
print("got exception")
raise
finally:
print("free g_file_ptr")
self.libgio.g_object_unref(g_file_ptr)
if not uri_ptr:
print("free uri_ptr")
self.libgio.g_free(uri_ptr)
raise RuntimeError("No URI received from the gfile pointer for "
"{0!r}".format(path))
try:
print("getting uri")
uri = ctypes.c_char_p(uri_ptr).value
except:
print("got exception")
raise
finally:
print("free uri_ptr")
self.libgio.g_free(uri_ptr)
return uri
def test():
gio = GioURI()
if not gio.available:
print("no gio")
return
for i in range(10):
print("Step %s" % i)
gio.uri(b"/foo/bar")
if __name__ == '__main__':
test()
#include <stdio.h>
#include <gio/gio.h>
int main() {
int i;
GFile* f;
const char* path = "/foo/bar";
char* uri;
for(i = 0; i < 100; i++) {
f = g_file_new_for_path(path);
printf("%i ", f);
uri = g_file_get_uri(f);
g_object_unref(f);
printf("%s\n", uri);
}
return 0;
}
--
https://mail.python.org/mailman/listinfo/python-list