1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_DynamicallyLinkedFunctionPtr_h
8 #define mozilla_DynamicallyLinkedFunctionPtr_h
14 #include "mozilla/Attributes.h"
20 struct FunctionPtrCracker
;
22 template <typename R
, typename
... Args
>
23 struct FunctionPtrCracker
<R (*)(Args
...)> {
25 using FunctionPtrT
= R (*)(Args
...);
29 template <typename R
, typename
... Args
>
30 struct FunctionPtrCracker
<R(__stdcall
*)(Args
...)> {
32 using FunctionPtrT
= R(__stdcall
*)(Args
...);
35 template <typename R
, typename
... Args
>
36 struct FunctionPtrCracker
<R(__fastcall
*)(Args
...)> {
38 using FunctionPtrT
= R(__fastcall
*)(Args
...);
40 #endif // defined(_M_IX86)
43 class DynamicallyLinkedFunctionPtrBase
{
45 using ReturnT
= typename FunctionPtrCracker
<T
>::ReturnT
;
46 using FunctionPtrT
= typename FunctionPtrCracker
<T
>::FunctionPtrT
;
48 DynamicallyLinkedFunctionPtrBase(const wchar_t* aLibName
,
49 const char* aFuncName
)
50 : mModule(::LoadLibraryW(aLibName
)), mFunction(nullptr) {
56 reinterpret_cast<FunctionPtrT
>(::GetProcAddress(mModule
, aFuncName
));
59 // Since the function doesn't exist, there is no point in holding a
60 // reference to mModule anymore.
61 ::FreeLibrary(mModule
);
66 DynamicallyLinkedFunctionPtrBase(const DynamicallyLinkedFunctionPtrBase
&) =
68 DynamicallyLinkedFunctionPtrBase
& operator=(
69 const DynamicallyLinkedFunctionPtrBase
&) = delete;
71 DynamicallyLinkedFunctionPtrBase(DynamicallyLinkedFunctionPtrBase
&&) = delete;
72 DynamicallyLinkedFunctionPtrBase
& operator=(
73 DynamicallyLinkedFunctionPtrBase
&&) = delete;
75 template <typename
... Args
>
76 ReturnT
operator()(Args
&&... args
) const {
77 return mFunction(std::forward
<Args
>(args
)...);
80 explicit operator bool() const { return !!mFunction
; }
84 FunctionPtrT mFunction
;
90 * In most cases, this class is the one that you want to use for resolving a
91 * dynamically-linked function pointer. It should be instantiated as a static
94 * NB: It has a trivial destructor, so the DLL that is loaded is never freed.
95 * Assuming that this function is called fairly often, this is the most
96 * sensible option. OTOH, if the function you are calling is a one-off, or the
97 * static local requirement is too restrictive, use DynamicallyLinkedFunctionPtr
100 template <typename T
>
101 class MOZ_STATIC_LOCAL_CLASS StaticDynamicallyLinkedFunctionPtr final
102 : public detail::DynamicallyLinkedFunctionPtrBase
<T
> {
104 StaticDynamicallyLinkedFunctionPtr(const wchar_t* aLibName
,
105 const char* aFuncName
)
106 : detail::DynamicallyLinkedFunctionPtrBase
<T
>(aLibName
, aFuncName
) {}
109 * We only offer this operator for the static local case, as it is not
110 * possible for this object to be destroyed while the returned pointer is
113 operator typename
detail::DynamicallyLinkedFunctionPtrBase
<T
>::FunctionPtrT()
115 return this->mFunction
;
119 template <typename T
>
120 class MOZ_NON_PARAM MOZ_NON_TEMPORARY_CLASS DynamicallyLinkedFunctionPtr final
121 : public detail::DynamicallyLinkedFunctionPtrBase
<T
> {
123 DynamicallyLinkedFunctionPtr(const wchar_t* aLibName
, const char* aFuncName
)
124 : detail::DynamicallyLinkedFunctionPtrBase
<T
>(aLibName
, aFuncName
) {}
126 ~DynamicallyLinkedFunctionPtr() {
127 if (!this->mModule
) {
131 ::FreeLibrary(this->mModule
);
135 } // namespace mozilla
137 #endif // mozilla_DynamicallyLinkedFunctionPtr_h