int tLuaCOMEnumerator::call_method(lua_State *L)
{
  /// positions of parameters
  
  // self param (not used, but explicited to ensure
  // consistency)
  const int self_param        = 1;

  // first user param 
  const int user_first_param  = 2;
  
  // last user param, excluding upvalues
  const int user_last_param   = luaCompat_getNumParams(L, 2);

  // upvalues
  const int enumerator_param  = luaCompat_upvalueIndex(L, 1, 2);
  const int method_param      = luaCompat_upvalueIndex(L, 2, 2);

  int num_params = 0;

  if(user_last_param < user_first_param)
    num_params = 0;
  else
    num_params = user_last_param - user_first_param + 1;

  // gets the enumerator
  tLuaCOMEnumerator* enumerator = 
    (tLuaCOMEnumerator*) luaCompat_getTypedObject(L, enumerator_param);

  // gets the method name
  const char* method_name = lua_tostring(L, method_param);

  // call method
  int retval = 0;

  try
  {
    retval = enumerator->callCOMmethod(L, method_name, user_first_param, num_params);
  }
  catch(class tLuaCOMException& e)
  {
    luacom_error(L, e.getMessage());

    return 0;
  }

  return retval;
}
// lua C function that dispatches events
// to sinks
int tLuaCOMConnPoint::call_sinks(lua_State *L)
{
  /// positions of parameters
  
  // self param (not used, but needed for ensuring
  // consistency
  const int self_param        = 1;

  // first user param 
  const int user_first_param  = 2;
  
  // last user param, excluding upvalues
  const int user_last_param   = luaCompat_getNumParams(L, 2);

  // upvalues
  const int connpoint         = luaCompat_upvalueIndex(L, 1, 2);
  const int event             = luaCompat_upvalueIndex(L, 2, 2);

  int num_params = 0;

  if(user_last_param < user_first_param)
    num_params = 0;
  else
    num_params = user_last_param - user_first_param + 1;

  // counter
  int i = 0;
   
  // gets connection point
  tLuaCOMConnPoint* cp = 
    (tLuaCOMConnPoint*) luaCompat_getPointer(L, connpoint);

  // call each sink
  for(i = 0; i < (int)cp->cConnections; i++)
  {
    // pushes function
    LuaBeans::push(L, cp->sinks[i]);
    cp->sinks[i]->Lock();

    lua_pushvalue(L, event);
    lua_gettable(L, -2);
    
    // removes table, leaving just function
    lua_remove(L, -2);

    // self param (mandatory but unused)
    LuaBeans::push(L, cp->sinks[i]);
    cp->sinks[i]->Lock();

    // duplicates parameters (if any)
    for(i = user_first_param; i <= user_last_param; i++)
    {
      lua_pushvalue(L, i);
    }

    // calls function (including self param)
    // ignoring errors
    luaCompat_call(L, num_params+1, 0, NULL);

    // cleans stack
    lua_settop(L, user_last_param);
  }

  // events do not return nothing
  return 0;
}