office-gobmx/bridges/source/net_uno/net_proxy.cxx
Mike Kaganski ad686b26ce No need to use SAL_THROW_EXTERN_C macro in CXX
Change-Id: I6eb9f0431a9402479a2d90d5b6f68b611d52a9f9
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175957
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2024-11-02 22:16:06 +01:00

173 lines
5.9 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "net_proxy.hxx"
#include "net_base.hxx"
#include <bridges/net_uno/net_context.hxx>
namespace net_uno
{
namespace
{
void SAL_CALL NetProxy_acquire(uno_Interface* pUnoI) noexcept
{
NetProxy* that = static_cast<NetProxy*>(pUnoI);
that->acquire();
}
void SAL_CALL NetProxy_release(uno_Interface* pUnoI) noexcept
{
NetProxy* that = static_cast<NetProxy*>(pUnoI);
that->release();
}
void SAL_CALL NetProxy_free([[maybe_unused]] uno_ExtEnvironment* pEnv, void* pUnoI) noexcept
{
NetProxy* that = static_cast<NetProxy*>(pUnoI);
delete that;
}
void SAL_CALL NetProxy_dispatch(uno_Interface* pUnoI, const typelib_TypeDescription* pMemberTD,
void* pUnoRet, void** pUnoArgs, uno_Any** pUnoExc) noexcept
{
NetProxy* proxy = static_cast<NetProxy*>(pUnoI);
try
{
switch (pMemberTD->eTypeClass)
{
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
{
const typelib_InterfaceAttributeTypeDescription* pAttribTD
= reinterpret_cast<const typelib_InterfaceAttributeTypeDescription*>(pMemberTD);
if (pUnoRet) // getter
{
proxy->m_bridge.call_net_func(proxy->m_netI, pMemberTD,
pAttribTD->pAttributeTypeRef, 0, nullptr, nullptr,
pUnoRet, pUnoExc);
}
else // setter
{
typelib_MethodParameter param;
param.pTypeRef = pAttribTD->pAttributeTypeRef;
param.bIn = true;
param.bOut = false;
proxy->m_bridge.call_net_func(proxy->m_netI, pMemberTD, nullptr, 1, &param,
pUnoArgs, nullptr, pUnoExc);
}
break;
}
case typelib_TypeClass_INTERFACE_METHOD:
{
const typelib_InterfaceMethodTypeDescription* pMethodTD
= reinterpret_cast<const typelib_InterfaceMethodTypeDescription*>(pMemberTD);
sal_Int32 nMemberPos = pMethodTD->aBase.nPosition;
assert(nMemberPos < proxy->m_TD->nAllMembers);
sal_Int32 nFunctionPos = proxy->m_TD->pMapMemberIndexToFunctionIndex[nMemberPos];
assert(nFunctionPos < proxy->m_TD->nMapFunctionIndexToMemberIndex);
switch (nFunctionPos)
{
case 1: // acquire()
NetProxy_acquire(proxy);
*pUnoExc = nullptr;
break;
case 2: // release()
NetProxy_release(proxy);
*pUnoExc = nullptr;
break;
default: // arbitrary method call
proxy->m_bridge.call_net_func(
proxy->m_netI, pMemberTD, pMethodTD->pReturnTypeRef, pMethodTD->nParams,
pMethodTD->pParams, pUnoArgs, pUnoRet, pUnoExc);
break;
}
break;
}
default:
{
throw BridgeRuntimeError(SAL_WHERE,
"could not find function "
+ OUString::unacquired(&pMemberTD->pTypeName));
}
}
}
catch (const BridgeRuntimeError& err)
{
SAL_WARN("bridges", ".NET bridge error: " << err.m_message);
css::uno::RuntimeException exc("[net_uno bridge error] " + err.m_message,
css::uno::Reference<css::uno::XInterface>());
uno_type_any_construct(*pUnoExc, &exc,
cppu::UnoType<css::uno::RuntimeException>::get().getTypeLibType(),
nullptr);
}
}
}
NetProxy::NetProxy(Bridge& rBridge, IntPtr pNetI, typelib_InterfaceTypeDescription* pTD,
const OUString& sOid)
: m_ref(1)
, m_bridge(rBridge)
, m_netI(nullptr)
, m_oid(sOid)
, m_TD(pTD)
{
void* that = this;
(*m_bridge.m_uno_env->registerProxyInterface)(m_bridge.m_uno_env, &that, NetProxy_free,
m_oid.pData, m_TD);
OUString sInterfaceName = map_uno_type_to_net(pTD->aBase.pWeakRef);
Context* pCtx = static_cast<Context*>(m_bridge.m_net_env->pContext);
m_netI = pCtx->registerInterface(pNetI, m_oid.getStr(), sInterfaceName.getStr());
m_bridge.acquire();
uno_Interface::acquire = NetProxy_acquire;
uno_Interface::release = NetProxy_release;
uno_Interface::pDispatcher = NetProxy_dispatch;
}
NetProxy::~NetProxy()
{
OUString sInterfaceName = map_uno_type_to_net(m_TD->aBase.pWeakRef);
static_cast<Context*>(m_bridge.m_net_env->pContext)
->revokeInterface(m_oid.getStr(), sInterfaceName.getStr());
m_bridge.release();
}
void NetProxy::acquire()
{
// rebirth of proxy zombie
if (osl_atomic_increment(&m_ref) == 1)
{
void* that = this;
(*m_bridge.m_uno_env->registerProxyInterface)(m_bridge.m_uno_env, &that, NetProxy_free,
m_oid.pData, m_TD);
}
}
void NetProxy::release()
{
// revoke from uno env on last release
if (osl_atomic_decrement(&m_ref) == 0)
{
(*m_bridge.m_uno_env->revokeInterface)(m_bridge.m_uno_env, this);
}
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */