[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