Illegal instruction on layers of callback wrappers

Thomas Stover <[email protected]> Thu, 12 May 2011 18:01:09 -0500
Newsgroups gmane.comp.python.ctypes
Message-ID <[email protected]>
I finally finished a stripped down example that reproduces the problem.

== glibcallback.c ======

#include <glib.h>

gboolean g_timeout_wrapper(gpointer data)
{
 /* explicit type cast from void * to function pointer */
 int (*callback) (int) = (int (*) (int)) data;
 int x;

 g_print("g_timeout_wrapper(): I'm going to call the my callback...\n");

 x = callback(5);

 g_print("callback returned %d\n", x);

 return TRUE;
}

int use_callback( int (*callback) (int) )
{
 g_print("use_callback(): wait 3 seconds...\n");
 g_timeout_add_seconds(3, g_timeout_wrapper, callback);
 return 0;
}
========================
gcc -c -fpic glibcallback.c `pkg-config --cflags glib-2.0`
gcc -shared -Wl-soname,libglibcallback.so.0.1 -o libglibcallback.so.0.0.1
glibcallback.o `pkg-config --libs glib-2.0`


====glibcallback.py================

#!/usr/bin/env python
from sys import *
from ctypes import *
import glib

def CallbackFromPython(y):
	print "CallbackFromPython()"
	return y + 5

class GlibCallback:
	def CallbackWrapper(self, y):
		return self.callback_variable(y)

	def __init__(self, callback_variable):
		cdll.LoadLibrary("libglibcallback.so.0.1")
		ctype_object = CDLL("libglibcallback.so.0.1")
		set_conversion_mode("utf-8", "strict")
		CALLBACK_TYPE = CFUNCTYPE(c_int, c_int)
		use_callback = ctype_object.use_callback
		use_callback.restype = c_int
		use_callback.argtypes = [CALLBACK_TYPE]
		callback = CALLBACK_TYPE(self.CallbackWrapper)
		use_callback(callback)
		self.callback_variable = CallbackFromPython

MainLoop = glib.MainLoop()

Obj = GlibCallback(CallbackFromPython)

MainLoop.run()

===================================
LD_LIBRARY_PATH=./ python ./glibcallback.py
use_callback(): wait 3 seconds...
g_timeout_wrapper(): I'm goint to call the my callback...
Illegal instruction 
or some runs: Segmentation fault
====================================



On the other hand it works if you take out the extra python wrapper or
make it not a instance method (correct python terminology?) eg...


def CallbackFromPython(y):
	print "CallbackFromPython()"
	return y + 5

cdll.LoadLibrary("libglibcallback.so.0.1")
ctype_object = CDLL("libglibcallback.so.0.1")
set_conversion_mode("utf-8", "strict")
CALLBACK_TYPE = CFUNCTYPE(c_int, c_int)
use_callback = ctype_object.use_callback
use_callback.restype = c_int
use_callback.argtypes = [CALLBACK_TYPE]
callback = CALLBACK_TYPE(CallbackFromPython)

MainLoop = glib.MainLoop()

use_callback(callback)

MainLoop.run()


yeilds:

use_callback(): wait 3 seconds...
g_timeout_wrapper(): I'm goint to call the my callback...
CallbackFromPython()
callback returned 10
g_timeout_wrapper(): I'm goint to call the my callback...
CallbackFromPython()
callback returned 10


This can't be a bug. Surely I'm doing something wrong. Ideas?


-- 
www.thomasstover.com
FLYNN LIVES!

------------------------------------------------------------------------------
Achieve unprecedented app performance and reliability
What every C/C++ and Fortran developer should know.
Learn how Intel has extended the reach of its next-generation tools
to help boost performance applications - inlcuding clusters.
http://p.sf.net/sfu/intel-dev2devmay