[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-bindings
Subject:    Re: [Kde-bindings] Qyoto: SIGNALS/SLOTS
From:       Arno Rehn <kde-bindings () arnorehn ! de>
Date:       2005-12-26 22:48:44
Message-ID: 200512270131.15792.kde-bindings () arnorehn ! de
[Download RAW message or body]

Am Samstag, 24. Dezember 2005 19:05 schrieb Arno Rehn:
> Am Freitag, 23. Dezember 2005 23:33 schrieb Arno Rehn:
> > Am Montag, 19. Dezember 2005 17:21 schrieb Adam Treat:
> > > On Monday December 19 2005 7:02 am, Richard Dale wrote:
> > > > In Qyoto the '_smokeObject' is a pointer directly to the C++
> > > > instance, it is a struct which contains that pointer, along with
> > > > several other things. So it is the direct equivalent of the Qt#
> > > > QtSharp class.
> > > >
> > > > From qyoto.h:
> > > >
> > > > struct smokeqyoto_object {
> > > >     bool allocated;
> > > >     Smoke *smoke;
> > > >     int classId;
> > > >     void *ptr;
> > > > };
> > > >
> > > > The 'ptr' field is the C++ instance. 'allocated' is true if the C#
> > > > instance was allocated from the C# side, or false if an existing C++
> > > > instance was wrapped, and the C++ instance shouldn't be deleted on
> > > > garbage collection. 'classId' is a numeric identifier that is used in
> > > > the lookup tables inside the Smoke library. 'smoke' is a  handle to
> > > > the Smoke library instance being used for the class (always the same
> > > > for every class in the current implementation).
> > >
> > > Ahh, that is cool.  I had something similar for libqtsharp.  So, Arno,
> > > it looks like the problem you were having was you were trying to
> > > connect the smoke object directly, instead of the underlying QObject
> > > which is the void ptr.  However, I think Richard is absolutely right,
> > > you don't want to be using Qt#'s libqtsharp for signal/slot connections
> > > on the C/C++ side of things when SMOKE will provide this for you. 
> > > Better to do it the SMOKE way since that is the binding library.
> >
> > Ok, I think I can do it now the 'non-SMOKE-way'. But I agree it would be
> > better to do it the SMOKE way. But what would that be?
>
> Yepp, I actually DID it the 'non-SMOKE-way'. I uploaded the modified files
> and commented them well, so it should be very easy to understand. Please
> note that libqtsharp.so from Qt# is needed.
> I know it is not very good to use the Qt#-way but it is a point from where
> we could start.
>
> http://www.arnorehn.de/programming/qyoto_signals.tar.gz

Ok, another question:
Today I tried to get return values working. I modified 'CallMethod' in 
qt3qyoto.cpp to get the return value of 'MethodCall.var()' in 
SmokeInvocation.cs. That worked and I can get the value of methods which 
return an 'int' (I haven't tested other types) via the StackItem-struct. I 
think it will also go well with 'long', 'byte', etc. But when the method 
returns a string I don't know what to do. How do I get a string out of 
'StackItem' ?
See attached files.

-- 
Arno Rehn
arno@arnorehn.de

["qt3qyoto.cpp" (text/x-c++src)]

/***************************************************************************
                          qyoto.cpp  -  description
                             -------------------
    begin                : Wed Jun 16 2004
    copyright            : (C) 2004 by Richard Dale
    email                : Richard_Dale@tipitina.demon.co.uk
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>

#include <qstring.h>
#include <qptrdict.h>
#include <qintdict.h>
#include <qobject.h>
#include <qpushbutton.h>

#undef DEBUG
#ifndef __USE_POSIX
#define __USE_POSIX
#endif
#ifndef __USE_XOPEN
#define __USE_XOPEN
#endif
#ifdef _BOOL
#define HAS_BOOL
#endif                                                          

#ifndef QT_VERSION_STR
#define QT_VERSION_STR "Unknown"
#endif

#include "marshall.h"
#include "qyoto.h"
#include "smokeqyoto.h"
#include "smoke.h"

#define QYOTO_VERSION "0.0.1"

extern Smoke *qt_Smoke;
extern void init_qt_Smoke();

#ifdef DEBUG
int do_debug = qtdb_gc;
#else
int do_debug = qtdb_none;
#endif

static GetIntPtr GetSmokeObject;
static SetIntPtr SetSmokeObject;

static SetIntPtr MapPointer;
static RemoveIntPtr UnmapPointer;
static GetIntPtr GetPointerObject;

// Maps from a classname in the form Qt::Widget to an int id
QIntDict<char> classname(2179);

extern "C" {
extern void * set_obj_info(const char * className, smokeqyoto_object * o);
};

extern bool isDerivedFromByName(Smoke *smoke, const char *className, const char \
*baseClassName); extern void mapPointer(void * obj, smokeqyoto_object *o, \
Smoke::Index classId, void *lastptr);

extern TypeHandler Qt_handlers[];
void install_handlers(TypeHandler *);

smokeqyoto_object *value_obj_info(void * qyoto_value) {  // ptr on success, null on \
fail  smokeqyoto_object * o = (smokeqyoto_object*) (*GetSmokeObject)(qyoto_value);
    return o;
}

bool isDerivedFrom(Smoke *smoke, Smoke::Index classId, Smoke::Index baseId) {
    if(classId == baseId)
	return true;
    for(Smoke::Index *p = smoke->inheritanceList + smoke->classes[classId].parents;
	*p;
	p++) {
	if(isDerivedFrom(smoke, *p, baseId))
	    return true;
    }
    return false;
}

bool isDerivedFromByName(Smoke *smoke, const char *className, const char \
*baseClassName) {  if(!smoke || !className || !baseClassName)
	return false;
    Smoke::Index idClass = smoke->idClass(className);
    Smoke::Index idBase = smoke->idClass(baseClassName);
    return isDerivedFrom(smoke, idClass, idBase);
}

void * getPointerObject(void *ptr) {
	return (*GetPointerObject)(ptr);
}

void unmapPointer(smokeqyoto_object *o, Smoke::Index classId, void *lastptr) {
    void *ptr = o->smoke->cast(o->ptr, o->classId, classId);
    if(ptr != lastptr) {
	lastptr = ptr;
	if (getPointerObject(ptr) != 0) {
		void * obj_ptr = getPointerObject(ptr);
		
		if (do_debug & qtdb_gc) {
			const char *className = o->smoke->classes[o->classId].className;
			printf("unmapPointer (%s*)%p -> %p", className, ptr, obj_ptr);
		}
	    
		(*UnmapPointer)(ptr);
	}
    }
    for(Smoke::Index *i = o->smoke->inheritanceList + \
                o->smoke->classes[classId].parents;
	*i;
	i++) {
	unmapPointer(o, *i, lastptr);
    }
}

// Store pointer in a Hashtable : "pointer_to_Qt_object" => weak ref to associated C# \
object // Recurse to store it also as casted to its parent classes.

void mapPointer(void * obj, smokeqyoto_object *o, Smoke::Index classId, void \
*lastptr) {  void *ptr = o->smoke->cast(o->ptr, o->classId, classId);
	
    if (ptr != lastptr) {
		lastptr = ptr;
//		if (do_debug & qtdb_gc) {
			const char *className = o->smoke->classes[o->classId].className;
			printf("mapPointer (%s*)%p -> %p", className, ptr, (void*)obj);
//		}
		(*MapPointer)(ptr, obj);
    }
	
    for(Smoke::Index *i = o->smoke->inheritanceList + \
                o->smoke->classes[classId].parents;
	*i;
	i++) {
	mapPointer(obj, o, *i, lastptr);
    }
	
	return;
}

void *
set_obj_info(const char * className, smokeqyoto_object * o)
{
//    VALUE klass = rb_funcall(qt_internal_module,
//			     rb_intern("find_class"),
//			     1,
//			     rb_str_new2(className) );
//    VALUE obj = Data_Wrap_Struct(klass, smokeruby_mark, smokeruby_free, (void *) \
o);  return 0;
}

Marshall::HandlerFn getMarshallFn(const SmokeType &type);

class MethodReturnValue : public Marshall {
    Smoke *_smoke;
    Smoke::Index _method;
    Smoke::StackItem & _retval;
    Smoke::Stack _stack;
public:
	MethodReturnValue(Smoke *smoke, Smoke::Index method, Smoke::Stack stack, \
Smoke::StackItem & retval) :  _smoke(smoke), _method(method), _retval(retval), \
_stack(stack) { printf("In MethodReturnValue(), type: %s _stack[0] %p\n", \
type().name(), _stack[0]);  Marshall::HandlerFn fn = getMarshallFn(type());
printf("In MethodReturnValue(), about to call return value marshaller\n");
		(*fn)(this);
    }

    const Smoke::Method &method() { return _smoke->methods[_method]; }
    SmokeType type() { return SmokeType(_smoke, method().ret); }
    Marshall::Action action() { return Marshall::ToObject; }
    Smoke::StackItem &item() { return _stack[0]; }
    Smoke::StackItem &var() {
    	return _retval;
    }
    void unsupported() {
//	rb_raise(rb_eArgError, "Cannot handle '%s' as return-type of %s::%s",
//		type().name(),
//		strcmp(_smoke->className(method().classId), "QGlobalSpace") == 0 ? "" : \
_smoke->className(method().classId), //		_smoke->methodNames[method().name]);
    }
    Smoke *smoke() { return _smoke; }
    void next() {}
    bool cleanup() { return false; }
};

class MethodCall : public Marshall {
    int _cur;
    Smoke *_smoke;
    Smoke::Stack _stack;
    Smoke::Index _method;
    Smoke::Index *_args;
	void * _target;
	void * _current_object;
	Smoke::Index _current_object_class;
    Smoke::Stack _sp;
    int _items;
    Smoke::StackItem _retval;
    bool _called;
public:
    MethodCall(Smoke *smoke, Smoke::Index method, void * target, Smoke::Stack sp, int \
items) :  _cur(-1), _smoke(smoke), _method(method), _target(target), \
_current_object(0), _sp(sp), _items(items), _called(false)  {
	if (_target != 0) {
	    smokeqyoto_object *o = value_obj_info(_target);
		if (o && o->ptr) {
		    _current_object = o->ptr;
		    _current_object_class = o->classId;
			printf("o->ptr: %p o->classId: %d\n", o->ptr, o->classId);
		}
	}
	
	_args = _smoke->argumentList + _smoke->methods[_method].args;
	_items = _smoke->methods[_method].numArgs;
	_stack = new Smoke::StackItem[items + 1];
//	_retval = 0;
    }

    ~MethodCall() {
	delete[] _stack;
    }

    SmokeType type() {
    	return SmokeType(_smoke, _args[_cur]);
    }

    Marshall::Action action() {
    	return Marshall::FromObject;
    }
    Smoke::StackItem &item() {
    	return _stack[_cur + 1];
    }

    Smoke::StackItem &var() {
	if(_cur < 0) return _retval;
	return _sp[_cur + 1];
    }

    inline const Smoke::Method &method() {
    	return _smoke->methods[_method];
    }

    void unsupported() {
    	if (strcmp(_smoke->className(method().classId), "QGlobalSpace") == 0) {
//			rb_raise(rb_eArgError, "Cannot handle '%s' as argument to %s",
//				type().name(),
//				_smoke->methodNames[method().name]);
		} else {
//			rb_raise(rb_eArgError, "Cannot handle '%s' as argument to %s::%s",
//				type().name(),
//				_smoke->className(method().classId),
//				_smoke->methodNames[method().name]);
		}
    }

    Smoke *smoke() {
    	return _smoke;
    }

	inline void callMethod() {
		if (_called) return;
		_called = true;
		Smoke::ClassFn fn = _smoke->classes[method().classId].classFn;
		void *ptr = _smoke->cast(_current_object, _current_object_class, method().classId);
		_items = -1;
		printf("In callMethod() fn: %p method().method: %d ptr: %p _stack[1]: %d\n", fn, \
method().method, ptr, _stack[1]);  (*fn)(method().method, ptr, _stack);
printf("In callMethod() _stack[0]: %p\n", _stack[0]);
		MethodReturnValue r(_smoke, _method, _stack, _retval);

		if (strcmp(_smoke->methodNames[method().name], _smoke->className(method().classId)) \
== 0) {  smokeqyoto_object  * o = (smokeqyoto_object *) \
malloc(sizeof(smokeqyoto_object));  o->smoke = _smoke;
			o->classId = method().classId;
			o->ptr = _stack[0].s_voidp;
			o->allocated = true;
			printf("In callMethod() o: %p\n",  o);
			(*SetSmokeObject)(_target, o);
		    mapPointer(_target, o, o->classId, 0);
		}

    }

    void next() {
	int oldcur = _cur;
	_cur++;

	while(!_called && _cur < _items) {
	    Marshall::HandlerFn fn = getMarshallFn(type());
	    (*fn)(this);
	    _cur++;
	}
	callMethod();
	_cur = oldcur;
    }

    bool cleanup() {
    	return true;
    }
};

class QyotoSmokeBinding : public SmokeBinding {
public:
    QyotoSmokeBinding(Smoke *s) : SmokeBinding(s) {}

    void deleted(Smoke::Index classId, void *ptr) {
	void * obj = getPointerObject(ptr);
	smokeqyoto_object *o = value_obj_info(obj);
	if(do_debug & qtdb_gc) {
	    printf("%p->~%s()", ptr, smoke->className(classId));
	}
	if(!o || !o->ptr) {
	    return;
	}
	unmapPointer(o, o->classId, 0);
	o->ptr = 0;
    }

    bool callMethod(Smoke::Index method, void *ptr, Smoke::Stack args, bool \
/*isAbstract*/) {  // Always fail for now..
		return false;

	void * obj = getPointerObject(ptr);
	smokeqyoto_object *o = value_obj_info(obj);
	if(do_debug & qtdb_virtual) 
	    printf("virtual %p->%s::%s() called", ptr,
		    smoke->classes[smoke->methods[method].classId].className,
		    smoke->methodNames[smoke->methods[method].name]
		    );

	if(!o) {
	    if( do_debug & qtdb_virtual )   // if not in global destruction
		printf("Cannot find object for virtual method %p -> %p", ptr, obj);
	    return false;
	}

	const char *methodName = smoke->methodNames[smoke->methods[method].name];
//	if (rb_respond_to(obj, rb_intern(methodName)) == 0) {
//	    return false;
//	}

//	VirtualMethodCall c(smoke, method, args, obj);
//	c.next();
	return true;
    }

    char *className(Smoke::Index classId) {
		return classname.find((int) classId);
    }
};

extern "C" {

int 
FindMethodId(char * classname, char * methodname) 
{
	Smoke::Index meth = qt_Smoke->findMethod(classname, methodname);
	printf("\t\tIn FindMethodId %s::%s => %d\n", classname, methodname, meth);
	return meth;
}

int 
MethodFromMap(int meth) 
{
	return qt_Smoke->methodMaps[meth].method;
}

int 
FindAmbiguousMethodId(int ambiguousId) 
{
	if (qt_Smoke->ambiguousMethodList[ambiguousId] == 0) {
		return 0;
	}
	
	Smoke::Method &methodRef = \
qt_Smoke->methods[qt_Smoke->ambiguousMethodList[ambiguousId]];  if ((methodRef.flags \
& Smoke::mf_internal) == 0) {  printf("\t\tIn FindAmbiguousMethodId(%d) => %d\n", \
ambiguousId, qt_Smoke->ambiguousMethodList[ambiguousId]);  return \
qt_Smoke->ambiguousMethodList[ambiguousId];  }
	
	return -1;
}

void AddGetSmokeObject(GetIntPtr callback)
{
	printf("In AddGetSmokeObject 0x%8.8x\n", callback);
	GetSmokeObject = callback;
}

void AddSetSmokeObject(SetIntPtr callback)
{
	printf("In AddSetSmokeObject 0x%8.8x\n", callback);
	SetSmokeObject = callback;
}

void AddMapPointer(SetIntPtr callback)
{
	printf("In AddMapPointer 0x%8.8x\n", callback);
	MapPointer = callback;
}

void AddUnmapPointer(RemoveIntPtr callback)
{
	printf("In AddUnmapPointer 0x%8.8x\n", callback);
	UnmapPointer = callback;
}

void AddGetPointerObject(GetIntPtr callback)
{
	printf("In AddGetPointerObject 0x%8.8x\n", callback);
	GetPointerObject = callback;
}

void
CallMethod(int methodId, void * obj, Smoke::StackItem * sp, int items)
{
	printf("In CallMethod methodId: %d target: 0x%8.8x items: %d\n", methodId, obj, \
items);  printf("In CallMethod %d\n", sp[1].s_int);
/*
	smokeqyoto_object  * o = (smokeqyoto_object *) malloc(sizeof(smokeqyoto_object));
	o->smoke = qt_Smoke;
	o->classId = 123;
	o->ptr = 0;
	o->allocated = false;
	(*SetSmokeObject)(obj, o);

	smokeqyoto_object * optr = (smokeqyoto_object *) (*GetSmokeObject)(obj);
	if (optr != 0) {
		printf("In CallMethod classId: %d\n", optr->classId);
	}
*/
	//Smoke::StackItem sp_return;
	
	MethodCall c(qt_Smoke, methodId, obj, sp, items);
	c.next();
	
	// to use the 'return-struct' in C# ...
	// not very nice, but this should be just a test and it works
	sp[0] = c.var();
	
//	sp[0].s_int = 0;
	//sp = &sp_return;
	return;
}


void
Init_qyoto()
{
	init_qt_Smoke();
	qt_Smoke->binding = new QyotoSmokeBinding(qt_Smoke);
	install_handlers(Qt_handlers);
}

}


["SmokeInvocation.cs" (text/x-c++src)]

/***************************************************************************
                          SmokeInvocation.cs  -  description
                             -------------------
    begin                : Wed Jun 16 2004
    copyright            : (C) 2004 by Richard Dale
    email                : Richard_Dale@tipitina.demon.co.uk
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

namespace Qt {

	using Qt;
	
	using System;
	using System.Collections;
	using System.Text;
	using System.Text.RegularExpressions;
	using System.Reflection;
	using System.Runtime.Remoting.Proxies;
	using System.Runtime.Remoting.Messaging;
	using System.Runtime.Remoting;
	using System.Runtime.InteropServices;

	[StructLayout(LayoutKind.Explicit)]
	unsafe public struct StackItem {
		[FieldOffset(0)] public void * s_voidp;
		[FieldOffset(0)] public bool s_bool;
		[FieldOffset(0)] public sbyte s_char;
		[FieldOffset(0)] public byte s_uchar;
		[FieldOffset(0)] public short s_short;
		[FieldOffset(0)] public ushort s_ushort;
		[FieldOffset(0)] public int s_int;
		[FieldOffset(0)] public uint s_uint;
		[FieldOffset(0)] public long s_long;
		[FieldOffset(0)] public ulong s_ulong;
		[FieldOffset(0)] public float s_float;
		[FieldOffset(0)] public double s_double;
        	[FieldOffset(0)] public long s_enum;
		[FieldOffset(0)] public void * s_class;
		[FieldOffset(0)] public IntPtr s_intptr;
	}
	
	public class SmokeInvocation : RealProxy {
		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
		static extern int FindMethodId(string className, string methodName);
			
		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
		static extern int MethodFromMap(int methodId);
			
		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
		static extern int FindAmbiguousMethodId(int ambigousId);
		
		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
		static extern void CallMethod(int methodId, IntPtr target, IntPtr sp, int items);
		
		delegate IntPtr GetIntPtr(IntPtr instance);
		delegate void SetIntPtr(IntPtr instance, IntPtr ptr);
		delegate void RemoveIntPtr(IntPtr ptr);
		
		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
		static extern IntPtr StringArrayToCharStarStar(int length, string[] strArray);
		
		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
		static extern IntPtr StringToQString(string str);

		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
		static extern void AddGetSmokeObject(GetIntPtr callback);
		
		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
		static extern void AddSetSmokeObject(SetIntPtr callback);
		
		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
		static extern void AddMapPointer(SetIntPtr callback);
		
		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
		static extern void AddUnmapPointer(RemoveIntPtr callback);
		
		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
		static extern void AddGetPointerObject(GetIntPtr callback);

		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
		static extern void AddIntPtrToCharStarStar(GetIntPtr callback);
		
		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
		static extern void AddIntPtrToQString(GetIntPtr callback);
		
		static IntPtr GetSmokeObject(IntPtr instancePtr) {
			Object instance = ((GCHandle) instancePtr).Target;
			if (instance == null) {
				return (IntPtr) 0;
			}
			// I modified the BindingFlags so '_smokeObject' is always correctly found
			FieldInfo fieldInfo = instance.GetType().GetField(	"_smokeObject", 
															BindingFlags.NonPublic
															| BindingFlags.Public
															| BindingFlags.GetField
															| BindingFlags.Instance );
			return (IntPtr) fieldInfo.GetValue(instance);
		}
		
		static void SetSmokeObject(IntPtr instancePtr, IntPtr smokeObjectPtr) {
			Object instance = ((GCHandle) instancePtr).Target;
			if (instance == null) {
				return;
			}
			// I modified the BindingFlags so '_smokeObject' is always correctly found
			FieldInfo fieldInfo = instance.GetType().GetField(	"_smokeObject", 
															BindingFlags.NonPublic
															| BindingFlags.Public
															| BindingFlags.GetField
															| BindingFlags.Instance );
			fieldInfo.SetValue(instance, smokeObjectPtr);
			return;
		}

		static void MapPointer(IntPtr ptr, IntPtr instancePtr) {
			Object instance = ((GCHandle) instancePtr).Target;
			WeakReference weakRef = new WeakReference(instance);
			pointerMap[ptr] = weakRef;
		}
		
		static void UnmapPointer(IntPtr ptr) {
			pointerMap.Remove(ptr);
		}
		
		static IntPtr testptr;
		
		static IntPtr GetPointerObject(IntPtr ptr) {
			testptr = ptr;
			Console.WriteLine("ENTER GetPointerObject() ptr: {0}", ptr);
			if (pointerMap[ptr] == null) {
				Console.WriteLine("GetPointerObject() pointerMap[ptr] == null");
				return (IntPtr) 0;
			}

			WeakReference weakRef = (WeakReference) pointerMap[ptr];
			if (weakRef == null) {
				Console.WriteLine("GetPointerObject() weakRef zero");
				return (IntPtr) 0;
			} else if (weakRef.IsAlive) {
				Console.WriteLine("GetPointerObject() weakRef.IsAlive");
				GCHandle instanceHandle = GCHandle.Alloc(weakRef.Target);
				return (IntPtr) instanceHandle;
			} else {
				Console.WriteLine("GetPointerObject() weakRef dead");
				return (IntPtr) 0;
			}
		}
		
		static IntPtr IntPtrToCharStarStar(IntPtr ptr) {
			string[] temp = (string[]) ((GCHandle) ptr).Target;
			Console.WriteLine("IntPtrToCharStarStar() string[0]: {0}", temp[0]);
			return StringArrayToCharStarStar(temp.Length, temp);
		}

		static IntPtr IntPtrToQString(IntPtr ptr) {
			string temp = (string) ((GCHandle) ptr).Target;
			Console.WriteLine("IntPtrToQString() string: {0}", temp);
			return StringToQString(temp);
		}

		static private Hashtable pointerMap = new Hashtable();
		static private GetIntPtr getSmokeObject = new GetIntPtr(GetSmokeObject);
		static private SetIntPtr setSmokeObject = new SetIntPtr(SetSmokeObject);
		
		static private SetIntPtr mapPointer = new SetIntPtr(MapPointer);
		static private RemoveIntPtr unmapPointer = new RemoveIntPtr(UnmapPointer);
		static private GetIntPtr getPointerObject = new GetIntPtr(GetPointerObject);
		
		static private GetIntPtr intPtrToCharStarStar = new \
GetIntPtr(IntPtrToCharStarStar);  static private GetIntPtr intPtrToQString = new \
GetIntPtr(IntPtrToQString);  
		static SmokeInvocation() {
			AddGetSmokeObject(getSmokeObject);
			AddSetSmokeObject(setSmokeObject);
			
			AddMapPointer(mapPointer);
			AddUnmapPointer(unmapPointer);
			AddGetPointerObject(getPointerObject);

			AddIntPtrToCharStarStar(intPtrToCharStarStar);
			AddIntPtrToQString(intPtrToQString);
		}
		
		private Type	_classToProxy;
		private Object	_instance;
		private string	_className;
		
		public SmokeInvocation(Type classToProxy, Object instance) : base(classToProxy) 
		{
			_classToProxy = classToProxy;
			_instance = instance;
			_className = Regex.Replace(_classToProxy.ToString(), @"^[^\.]*.([^+]*).*", "$1");
			
		}

		public ArrayList FindMethod(string name) {
			ArrayList result = new ArrayList();
			
			Console.WriteLine("FindMethod() className: {0} MethodName: {1}", _className, \
name);  int meth = FindMethodId(_className, name);
			if (meth == 0) {
				meth = FindMethodId("QGlobalSpace", name);
			}
			
			if (meth == 0) {
				return result;
			} else if (meth > 0) {
				int i = MethodFromMap(meth);
				Console.WriteLine("FindMethod() MethodName: {0} result: {1}", name, i);
				if (i == 0) {		// shouldn't happen
					;
				} else if (i > 0) {	// single match
					result.Add(i);
					Console.WriteLine("FindMethod() single match {0}", i);
				} else {		// multiple match
					i = -i;		// turn into ambiguousMethodList index
					int	methodId;
					while ((methodId = FindAmbiguousMethodId(i)) != 0) {
						if (methodId > 0) {
							result.Add(methodId);
						}
						i++;
					}
					Console.WriteLine("FindMethod() multiple match {0}", result[0]);
				}
			}
			return result;
		}
		
		public override IMessage Invoke(IMessage message) {
			ArrayList	methods = null;
			
			IMethodCallMessage callMessage = (IMethodCallMessage) message;
			Console.WriteLine(	"Invoke() MethodName: {0} Type: {1} ArgCount: {2}", 
								callMessage.MethodName, 
								callMessage.TypeName, 
								callMessage.ArgCount.ToString() );
			
			StackItem[] stack = new StackItem[callMessage.ArgCount+1];
			
			string mungedName = callMessage.MethodName;
			mungedName = char.ToLower(mungedName[0]) + mungedName.Substring(1, \
mungedName.Length-1);  mungedName = Regex.Replace(mungedName, @"^new", "");

			if (callMessage.MethodSignature != null) {
				Type[] types = (Type[]) callMessage.MethodSignature;
				for (int i = 0; i < callMessage.ArgCount; i++) {
					if (	types[i].IsArray
							|| types[i] == typeof(System.Collections.ArrayList) ) 
					{
						mungedName += "?";
					} else if (	types[i].IsPrimitive 
								|| types[i] == typeof(System.String) 
								|| types[i] == typeof(System.Text.StringBuilder) ) 
					{
						mungedName += "$";
					} else {
						mungedName += "#";
					}
				}

				methods = FindMethod(mungedName);

				for (int i = 0; i < callMessage.ArgCount; i++) {
					if (callMessage.Args[i] == null) {
						unsafe {
							stack[i+1].s_intptr = (IntPtr) 0;
						}
					} else if (types[i] == typeof(bool)) {
						stack[i+1].s_bool = (bool) callMessage.Args[i];
					} else if (types[i] == typeof(sbyte)) {
						stack[i+1].s_char = (sbyte) callMessage.Args[i];
					} else if (types[i] == typeof(byte)) {
						stack[i+1].s_uchar = (byte) callMessage.Args[i];
					} else if (types[i] == typeof(short)) {
						stack[i+1].s_short = (short) callMessage.Args[i];
					} else if (types[i] == typeof(ushort)) {
						stack[i+1].s_ushort = (ushort) callMessage.Args[i];
					} else if (types[i] == typeof(int)) {
						stack[i+1].s_int = (int) callMessage.Args[i];
					} else if (types[i] == typeof(uint)) {
						stack[i+1].s_uint = (uint) callMessage.Args[i];
					} else if (types[i] == typeof(long)) {
						stack[i+1].s_long = (long) callMessage.Args[i];
					} else if (types[i] == typeof(ulong)) {
						stack[i+1].s_ulong = (ulong) callMessage.Args[i];
					} else if (types[i] == typeof(float)) {
						stack[i+1].s_float = (float) callMessage.Args[i];
					} else if (types[i] == typeof(double)) {
						stack[i+1].s_double = (double) callMessage.Args[i];
					} else {
						stack[i+1].s_intptr = (IntPtr) GCHandle.Alloc(callMessage.Args[i]);
//					} else if (types[i] == typeof(string[])) {
//						unsafe {
//							stack[i+1].s_voidp = (void *) StringArrayToCharStarStar((string[]) \
callMessage.Args[i]); //						}
					}
					if (callMessage.Args[i] == null) {
						Console.WriteLine(	"\tArgName: {0} Arg: null", 
											callMessage.GetArgName(i) );
					} else {
						Console.WriteLine(	"\tArgName: {0} Arg: {1} Type: {2}", 
											callMessage.GetArgName(i),
											callMessage.GetArg(i),
											callMessage.Args[i].GetType() );
					}
				}
			}
			
			GCHandle instanceHandle = GCHandle.Alloc(_instance);
			IntPtr instancePointer = (IntPtr) instanceHandle;
			//Console.WriteLine("**********\n{0}\n**********", instancePointer.ToInt64());
			
			
			object o_return = null;
			
			unsafe {
				fixed(StackItem * stackPtr = stack) {
					
					// I modified CallMethod to set the third parameter to the 'return-struct' so it \
                can be used in C#.
					CallMethod((int) methods[0], (IntPtr) instanceHandle, (IntPtr) stackPtr, \
callMessage.ArgCount);  Console.WriteLine("returned from CallMethod");
					
					// here we check what the return type of the C#-method is and set the appropiate \
value from the struct  MethodBase mb = callMessage.MethodBase;
					switch(GetReturnType(mb.ToString())) {
						case "Void":
							o_return = null;
							break;
							
						case "Int32":
							o_return = stack[0].s_int;
							//Console.WriteLine("************\nreturned: {0}\n************", \
stack[0].s_int);  break;
						
						case "Boolean":
							o_return = stack[0].s_bool;
							break;
						
						/**
						  * Do we really have to check for a 'SByte' or 'Byte' or just simply for a \
                'Char' ?
						  */
						case "SByte":
							o_return = stack[0].s_char;
							break;

						case "Byte":
							o_return = stack[0].s_uchar;
							break;
						
						case "Double":
							o_return = stack[0].s_double;
							break;

						case "Single":
							o_return = stack[0].s_float;
							break;
							
						// haven't done the other types yet.
					}
				}
			}
			
			instanceHandle.Free();
			
			if (_instance != null) {
//				Console.WriteLine(	"instance: {0} returned: {1}", 
//									_instance.GetType().ToString(), 
//									returnedInstance.GetType().ToString(),
//									stackItem[1].s_int );
			}
			
			IMethodReturnMessage returnMessage = (IMethodReturnMessage) message;
			
			/*
			if (returnMessage.MethodName.Equals("PointSize")) {
				MethodReturnMessageWrapper returnValue = new \
MethodReturnMessageWrapper((IMethodReturnMessage) returnMessage);   \
returnValue.ReturnValue = 17;  returnMessage = returnValue;
			}
			*/

			MethodReturnMessageWrapper returnValue = new \
MethodReturnMessageWrapper((IMethodReturnMessage) returnMessage);  
			//return the new object with the return value
			returnValue.ReturnValue = o_return;
			returnMessage = returnValue;

			return returnMessage;
		}
		
		
		/**
		  * new function to get the return type from a MethodBase
		  */
		private string GetReturnType(string MethodName) {
			int blank_pos = MethodName.IndexOf(' ');
			if (blank_pos != -1)
				return MethodName.Substring(0, blank_pos);
			return "";
		}
		
		public override int GetHashCode() {
			return _instance.GetHashCode();
		}
	}
}



_______________________________________________
Kde-bindings mailing list
Kde-bindings@kde.org
https://mail.kde.org/mailman/listinfo/kde-bindings


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic