1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <sal/config.h>
18 #include <com/sun/star/uno/Exception.hpp>
19 #include <com/sun/star/uno/RuntimeException.hpp>
20 #include <com/sun/star/uno/genfunc.hxx>
21 #include <cppu/unotype.hxx>
22 #include <o3tl/runtimetooustring.hxx>
23 #include <o3tl/temporary.hxx>
24 #include <o3tl/unreachable.hxx>
25 #include <rtl/strbuf.hxx>
26 #include <typelib/typeclass.h>
27 #include <typelib/typedescription.h>
28 #include <typelib/typedescription.hxx>
34 #include <unointerfaceproxy.hxx>
35 #include <vtables.hxx>
36 #include <wasm/generated.hxx>
42 void call(bridges::cpp_uno::shared::UnoInterfaceProxy
* proxy
,
43 bridges::cpp_uno::shared::VtableSlot slot
, typelib_TypeDescriptionReference
* returnType
,
44 sal_Int32 count
, typelib_MethodParameter
* parameters
, void* returnValue
, void** arguments
,
47 css::uno::TypeDescription
rtd(returnType
);
48 auto const retConv
= bridges::cpp_uno::shared::relatesToInterfaceType(rtd
.get());
49 auto const ret
= retConv
? alloca(rtd
.get()->nSize
) : returnValue
;
51 std::vector
<sal_uInt64
> args
;
52 switch (rtd
.get()->eTypeClass
)
54 case typelib_TypeClass_VOID
:
57 case typelib_TypeClass_BOOLEAN
:
58 case typelib_TypeClass_BYTE
:
59 case typelib_TypeClass_SHORT
:
60 case typelib_TypeClass_UNSIGNED_SHORT
:
61 case typelib_TypeClass_LONG
:
62 case typelib_TypeClass_UNSIGNED_LONG
:
63 case typelib_TypeClass_CHAR
:
64 case typelib_TypeClass_ENUM
:
67 case typelib_TypeClass_HYPER
:
68 case typelib_TypeClass_UNSIGNED_HYPER
:
71 case typelib_TypeClass_FLOAT
:
74 case typelib_TypeClass_DOUBLE
:
77 case typelib_TypeClass_STRING
:
78 case typelib_TypeClass_TYPE
:
79 case typelib_TypeClass_ANY
:
80 case typelib_TypeClass_SEQUENCE
:
81 case typelib_TypeClass_INTERFACE
:
83 args
.push_back(reinterpret_cast<sal_uInt32
>(ret
));
85 case typelib_TypeClass_STRUCT
:
87 switch (abi_wasm::getKind(
88 reinterpret_cast<typelib_CompoundTypeDescription
const*>(rtd
.get())))
90 case abi_wasm::StructKind::Empty
:
92 case abi_wasm::StructKind::I32
:
95 case abi_wasm::StructKind::I64
:
98 case abi_wasm::StructKind::F32
:
101 case abi_wasm::StructKind::F64
:
104 case abi_wasm::StructKind::General
:
106 args
.push_back(reinterpret_cast<sal_uInt32
>(ret
));
115 sal_uInt32
const* const* thisPtr
116 = reinterpret_cast<sal_uInt32
const* const*>(proxy
->getCppI()) + slot
.offset
;
117 args
.push_back(reinterpret_cast<sal_uInt32
>(thisPtr
));
118 std::vector
<void*> cppArgs(count
);
119 std::vector
<css::uno::TypeDescription
> ptds(count
);
120 for (sal_Int32 i
= 0; i
!= count
; ++i
)
122 if (!parameters
[i
].bOut
&& bridges::cpp_uno::shared::isSimpleType(parameters
[i
].pTypeRef
))
124 switch (parameters
[i
].pTypeRef
->eTypeClass
)
126 case typelib_TypeClass_BOOLEAN
:
128 args
.push_back(*reinterpret_cast<sal_Bool
const*>(arguments
[i
]));
130 case typelib_TypeClass_BYTE
:
132 args
.push_back(*reinterpret_cast<sal_Int8
const*>(arguments
[i
]));
134 case typelib_TypeClass_SHORT
:
136 args
.push_back(*reinterpret_cast<sal_Int16
const*>(arguments
[i
]));
138 case typelib_TypeClass_UNSIGNED_SHORT
:
140 args
.push_back(*reinterpret_cast<sal_uInt16
const*>(arguments
[i
]));
142 case typelib_TypeClass_LONG
:
143 case typelib_TypeClass_ENUM
:
145 args
.push_back(*reinterpret_cast<sal_Int32
const*>(arguments
[i
]));
147 case typelib_TypeClass_UNSIGNED_LONG
:
149 args
.push_back(*reinterpret_cast<sal_uInt32
const*>(arguments
[i
]));
151 case typelib_TypeClass_HYPER
:
153 args
.push_back(*reinterpret_cast<sal_Int64
const*>(arguments
[i
]));
155 case typelib_TypeClass_UNSIGNED_HYPER
:
157 args
.push_back(*reinterpret_cast<sal_uInt64
const*>(arguments
[i
]));
159 case typelib_TypeClass_FLOAT
:
161 args
.push_back(*reinterpret_cast<sal_uInt32
const*>(arguments
[i
]));
163 case typelib_TypeClass_DOUBLE
:
165 args
.push_back(*reinterpret_cast<sal_uInt64
const*>(arguments
[i
]));
167 case typelib_TypeClass_CHAR
:
169 args
.push_back(*reinterpret_cast<sal_Unicode
const*>(arguments
[i
]));
178 css::uno::TypeDescription
ptd(parameters
[i
].pTypeRef
);
179 if (!parameters
[i
].bIn
)
181 cppArgs
[i
] = alloca(ptd
.get()->nSize
);
182 uno_constructData(cppArgs
[i
], ptd
.get());
184 args
.push_back(reinterpret_cast<sal_uInt32
>(cppArgs
[i
]));
186 else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd
.get()))
188 cppArgs
[i
] = alloca(ptd
.get()->nSize
);
189 uno_copyAndConvertData(cppArgs
[i
], arguments
[i
], ptd
.get(),
190 proxy
->getBridge()->getUno2Cpp());
192 args
.push_back(reinterpret_cast<sal_uInt32
>(cppArgs
[i
]));
196 args
.push_back(reinterpret_cast<sal_uInt32
>(arguments
[i
]));
204 callVirtualFunction(sig
, (*thisPtr
)[slot
.index
], args
.data(), ret
);
206 catch (css::uno::Exception
&)
210 catch (std::exception
& e
)
212 throw css::uno::RuntimeException("C++ code threw "
213 + o3tl::runtimeToOUString(typeid(e
).name()) + ": "
214 + o3tl::runtimeToOUString(e
.what()));
218 throw css::uno::RuntimeException("C++ code threw unknown exception");
221 catch (css::uno::Exception
&)
223 __cxxabiv1::__cxa_exception
* header
224 = reinterpret_cast<__cxxabiv1::__cxa_eh_globals
*>(__cxxabiv1::__cxa_get_globals())
226 abi_wasm::mapException(header
, __cxxabiv1::__cxa_current_exception_type(), *exception
,
227 proxy
->getBridge()->getCpp2Uno());
228 for (sal_Int32 i
= 0; i
!= count
; ++i
)
230 if (cppArgs
[i
] != nullptr)
232 uno_destructData(cppArgs
[i
], ptds
[i
].get(),
233 reinterpret_cast<uno_ReleaseFunc
>(css::uno::cpp_release
));
238 *exception
= nullptr;
239 for (sal_Int32 i
= 0; i
!= count
; ++i
)
241 if (cppArgs
[i
] != nullptr)
243 if (parameters
[i
].bOut
)
245 if (parameters
[i
].bIn
)
247 uno_destructData(arguments
[i
], ptds
[i
].get(), nullptr);
249 uno_copyAndConvertData(arguments
[i
], cppArgs
[i
], ptds
[i
].get(),
250 proxy
->getBridge()->getCpp2Uno());
252 uno_destructData(cppArgs
[i
], ptds
[i
].get(),
253 reinterpret_cast<uno_ReleaseFunc
>(css::uno::cpp_release
));
258 uno_copyAndConvertData(returnValue
, ret
, rtd
.get(), proxy
->getBridge()->getCpp2Uno());
259 uno_destructData(ret
, rtd
.get(), reinterpret_cast<uno_ReleaseFunc
>(css::uno::cpp_release
));
264 namespace bridges::cpp_uno::shared
266 void unoInterfaceProxyDispatch(uno_Interface
* pUnoI
, const typelib_TypeDescription
* pMemberDescr
,
267 void* pReturn
, void* pArgs
[], uno_Any
** ppException
)
269 bridges::cpp_uno::shared::UnoInterfaceProxy
* pThis
270 = static_cast<bridges::cpp_uno::shared::UnoInterfaceProxy
*>(pUnoI
);
272 switch (pMemberDescr
->eTypeClass
)
274 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
277 = reinterpret_cast<typelib_InterfaceAttributeTypeDescription
const*>(pMemberDescr
);
278 VtableSlot
slot(getVtableSlot(atd
));
279 if (pReturn
== nullptr)
282 call(pThis
, slot
, cppu::UnoType
<void>::get().getTypeLibType(), 1,
284 typelib_MethodParameter
{ nullptr, atd
->pAttributeTypeRef
, true, false }),
285 pReturn
, pArgs
, ppException
);
289 call(pThis
, slot
, atd
->pAttributeTypeRef
, 0, nullptr, pReturn
, pArgs
, ppException
);
293 case typelib_TypeClass_INTERFACE_METHOD
:
295 VtableSlot
aVtableSlot(getVtableSlot(
296 reinterpret_cast<typelib_InterfaceMethodTypeDescription
const*>(pMemberDescr
)));
298 switch (aVtableSlot
.index
)
300 case 1: // acquire uno interface
301 (*pUnoI
->acquire
)(pUnoI
);
304 case 2: // release uno interface
305 (*pUnoI
->release
)(pUnoI
);
308 case 0: // queryInterface() opt
310 typelib_TypeDescription
* pTD
= 0;
312 &pTD
, reinterpret_cast<css::uno::Type
*>(pArgs
[0])->getTypeLibType());
315 uno_Interface
* pInterface
= 0;
316 (*pThis
->getBridge()->getUnoEnv()->getRegisteredInterface
)(
317 pThis
->getBridge()->getUnoEnv(), (void**)&pInterface
, pThis
->oid
.pData
,
318 (typelib_InterfaceTypeDescription
*)pTD
);
322 ::uno_any_construct(reinterpret_cast<uno_Any
*>(pReturn
), &pInterface
,
324 (*pInterface
->release
)(pInterface
);
325 TYPELIB_DANGER_RELEASE(pTD
);
329 TYPELIB_DANGER_RELEASE(pTD
);
331 } // else perform queryInterface()
336 = reinterpret_cast<typelib_InterfaceMethodTypeDescription
const*>(
338 call(pThis
, aVtableSlot
, mtd
->pReturnTypeRef
, mtd
->nParams
, mtd
->pParams
,
339 pReturn
, pArgs
, ppException
);
346 ::com::sun::star::uno::RuntimeException
aExc(
347 "illegal member type description!",
348 ::com::sun::star::uno::Reference
<::com::sun::star::uno::XInterface
>());
350 css::uno::Type
const& rExcType
= cppu::UnoType
<decltype(aExc
)>::get();
351 // binary identical null reference
352 ::uno_type_any_construct(*ppException
, &aExc
, rExcType
.getTypeLibType(), 0);
357 } // namespace bridges::cpp_uno::shared
359 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */