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

Reply via email to