2005/5/9

     
 

CreateTypeInfo.cpp

artefaktur
// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*- 
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
// 
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
// 
// 
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the 
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
//                         ACDK
// 
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
// 
// $Header: /cvsroot/acdk/acdk/acdkx_com/src/acdkx/com/CreateTypeInfo.cpp,v 1.16 2005/03/12 11:51:43 kommer Exp $

#include "CreateTypeLib.h"
#include "CoException.h"
#include "CreateTypeInfo.h"
#include <acdk/lang/reflect/Modifier.h>

namespace acdkx {
namespace com {

using acdk::lang::reflect::Modifier;
using namespace acdk::lang::dmi;

void toElemDesc(ELEMDESC& elemdesc, ClazzMethodArgInfo& mai)
{
  
}

namespace {

class ElementDescription
{
  bool _valid;
public:
  ElementDescription(ELEMDESC& elmd, ClazzMethodArgInfo& mai)
    : _valid(true)
  {
    memset(&elmd, 0, sizeof(ELEMDESC));
    
    if (mai.type == ClazzInfo::getCharClazz()) {
      elmd.tdesc.vt = VT_UI1;
      static TYPEDESC td = { 0 };
      td.vt = VT_INT;
      elmd.tdesc.lptdesc = &td;
    } else if (mai.type == ClazzInfo::getByteClazz()) {
      elmd.tdesc.vt = VT_UI1;
    } else if (mai.type == ClazzInfo::getShortClazz()) {
      elmd.tdesc.vt = VT_I2;
    } else if (mai.type == ClazzInfo::getIntClazz()) {
      elmd.tdesc.vt = VT_I4;
    } else if (mai.type == ClazzInfo::getLongClazz()) {
      elmd.tdesc.vt = VT_I4; // I8 not exists
    } else if (mai.type == ClazzInfo::getFloatClazz()) {
      elmd.tdesc.vt = VT_R4;
    } else if (mai.type == ClazzInfo::getDoubleClazz()) {
      elmd.tdesc.vt = VT_R8;
    } else if (mai.type == ClazzInfo::getBoolClazz()) {
      elmd.tdesc.vt = VT_BOOL;
    } else if (mai.type == ClazzInfo::getVoidClazz()) {
      elmd.tdesc.vt = VT_NULL;
    } else if (mai.type == String::clazzInfo()) {
      elmd.tdesc.vt =  VT_BSTR;
    } else if (mai.type->isArray() == true) {
      acdk::lang::Object::_throwNotImplementedYet("acdkx.com.arrays");
      _valid = false;
    } else {
      elmd.tdesc.vt = VT_INT;
      static TYPEDESC itd = { 0 };
      itd.vt = VT_INT;
      elmd.tdesc.lptdesc = &itd;
      //elmd.tdesc.vt =  VT_DISPATCH;
    } 
  }    
  bool isValid() const { return _valid; }
};

class FuncDescription
: public FUNCDESC
{
  bool _valid;
public:
  FuncDescription(ClazzInfo& clzinfo, ClazzMethodInfo& cmi)
    : _valid(false)
  {
    FUNCDESC* fd = this;
    memset(fd, 0, sizeof(FUNCDESC));
   
    set(clzinfo, cmi);
     _valid = true;
  }
  ~FuncDescription()
  {
    if (lprgelemdescParam != 0)
      delete[] lprgelemdescParam;
  }
  bool isValid() const { return _valid; }
  void setParamCount(int count)
  {
    cParams = count;
    //if (cParams > 0)
    lprgelemdescParam = new ELEMDESC[cParams];
    memset(lprgelemdescParam, 0, sizeof(ELEMDESC) * cParams);
  }
  bool set(ClazzInfo& clzinfo, ClazzMethodInfo& cmi)
  {
    invkind = INVOKE_FUNC;
    funckind = FUNC_DISPATCH;
    /*
    if (cmi.flags & Modifier::STATIC)
      funckind = FUNC_DISPATCH;
    else if (cmi.flags & Modifier::ABSTRACT)
      funckind = FUNC_DISPATCH;
      */
    int argcount = 0;
    int i;
    for (i = 0; cmi.methodArgs[i] != 0; ++i)
      ++argcount;
    if ( cmi.returnType != ClazzInfo::getVoidClazz())
      ++argcount;
    setParamCount(argcount);

    for (i = 0; cmi.methodArgs[i] != 0; ++i)
    {
      if (ElementDescription(lprgelemdescParam[i], *cmi.methodArgs[i]).isValid() == false)
        return false;
      
    }
    if ( cmi.returnType != ClazzInfo::getVoidClazz())
    {

      ClazzMethodArgInfo ret = { 0, 0, "", -1, "", 0, 0, cmi.returnType };
      if (ElementDescription(lprgelemdescParam[i], ret).isValid() == false)
        return false;
    }
    static TYPEDESC tdescUser = { 0 };
    elemdescFunc.tdesc.vt = VT_HRESULT;
    elemdescFunc.tdesc.lptdesc = &tdescUser;

    return true;
  }
  void registerFunction(int idx, ClazzMethodInfo& cmi, ICreateTypeInfo& cti)
  {
    memid = idx;
    // ### debug gest
    IID IID_ISum = {0x10000001,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}};
	  cti.SetGuid(IID_ISum);

    /*

  // Strukturen fuer die x, y und retval-Parameter der Sum-Methode
	TYPEDESC tdescParams = { 0 };
    tdescParams.vt = VT_INT;
	ELEMDESC myParams[3] = { 0 };
	myParams[0].tdesc.vt = VT_INT;
	myParams[0].tdesc.lptdesc = &tdescParams;
	myParams[1].tdesc.vt = VT_INT;
	myParams[1].tdesc.lptdesc = &tdescParams;
	myParams[2].tdesc.vt = VT_PTR;
	myParams[2].tdesc.lptdesc = &tdescParams;
	myParams[2].paramdesc.wParamFlags = PARAMFLAG_FRETVAL|PARAMFLAG_FOUT;

	// Zusaetzliche Daten, die die Sum-Methode und deren Rueckgabewert beschreiben
	TYPEDESC tdescUser = { 0 };
    FUNCDESC FuncDesc = { 0 };
	FuncDesc.funckind = FUNC_PUREVIRTUAL;
    FuncDesc.invkind = INVOKE_FUNC;
    FuncDesc.callconv = CC_STDCALL;

	// Parameter
	FuncDesc.cParams = 3;
	FuncDesc.lprgelemdescParam = myParams;

	// HRESULT Rueckgabewert
    FuncDesc.elemdescFunc.tdesc.vt = VT_HRESULT;
    FuncDesc.elemdescFunc.tdesc.lptdesc = &tdescUser;
    ACDK_CECKCOMCALL(cti.AddFuncDesc(idx, &FuncDesc));
    */
    funckind = FUNC_PUREVIRTUAL;
    //funckind = FUNC_DISPATCH;
    callconv = CC_STDCALL;
    ACDK_CECKCOMCALL(cti.AddFuncDesc(idx, this));

    const int MaxParams = 100;
    BSTR pnames[MaxParams];
    
    int _clength;
    int i = 0;
    pnames[i++] = CS2W(cmi.name);
    for (int j = 0; cmi.methodArgs[j] != 0; ++j)
    {
      pnames[i++] = CS2W(cmi.methodArgs[j]->name);
    }
    if ( cmi.returnType != ClazzInfo::getVoidClazz())
      pnames[++i] = CS2W("returnValue");
    //ACDK_CECKCOMCALL(
    cti.SetFuncAndParamNames(idx, pnames, i);
    
  }
};

} // anon namespaced

void 
CreateTypeInfo::createClass(IN(RClass) cls)
{
  if (cls->isInterface() == true) {
    _iface->SetTypeFlags(TYPEFLAG_FOLEAUTOMATION );
  } else  {
    _iface->SetTypeFlags(TYPEFLAG_FOLEAUTOMATION );
  }
  
  /*
    Set super (interfaces) here. If super are not registered, don't add or try to add
  */
  ClazzInfo* clzinfo = cls->clazzInfo();
  int ioffset = 0;
  for (int i = 0; clzinfo->methods[i]; ++i) 
  {
    FuncDescription fd(*clzinfo, *(clzinfo->methods[i]));
    if (fd.isValid() == true)
      fd.registerFunction(ioffset++, *(clzinfo->methods[i]), *_iface);
  }

}

} // namespace com 
} // namespace acdkx