Commit 6bc2e353 authored by Sorin Jianu's avatar Sorin Jianu Committed by Commit Bot

Allow base::Bind to bind __stdcall object methods for Windows x86.

The binding code is missing template definitions for
__stdcall object method invocations. Such template definitions
exists for functions but not for object methods.

This patch allows this code to compile:

class MethodHolder {
   public:
    int __stdcall Func(int n) { return n; }
    int __stdcall ConstFunc(int n) const { return -n; }
  };

  MethodHolder obj;
  auto stdcall_method_cb =
      BindRepeating(&MethodHolder::Func, base::Unretained(&obj), 1);


Bug: 1066580
Change-Id: I6ce3cbeb9b42ebcf75c64e33f464c4e4c5409a26
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2129895
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#755432}
parent 60852610
......@@ -505,6 +505,40 @@ struct FunctorTraits<R (Receiver::*)(Args...) const> {
}
};
#if defined(OS_WIN) && !defined(ARCH_CPU_64_BITS)
// For __stdcall methods.
template <typename R, typename Receiver, typename... Args>
struct FunctorTraits<R (__stdcall Receiver::*)(Args...)> {
using RunType = R(Receiver*, Args...);
static constexpr bool is_method = true;
static constexpr bool is_nullable = true;
template <typename Method, typename ReceiverPtr, typename... RunArgs>
static R Invoke(Method method,
ReceiverPtr&& receiver_ptr,
RunArgs&&... args) {
return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
}
};
// For __stdcall const methods.
template <typename R, typename Receiver, typename... Args>
struct FunctorTraits<R (__stdcall Receiver::*)(Args...) const> {
using RunType = R(const Receiver*, Args...);
static constexpr bool is_method = true;
static constexpr bool is_nullable = true;
template <typename Method, typename ReceiverPtr, typename... RunArgs>
static R Invoke(Method method,
ReceiverPtr&& receiver_ptr,
RunArgs&&... args) {
return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
}
};
#endif // defined(OS_WIN) && !defined(ARCH_CPU_64_BITS)
#ifdef __cpp_noexcept_function_type
// noexcept makes a distinct function type in C++17.
// I.e. `void(*)()` and `void(*)() noexcept` are same in pre-C++17, and
......
......@@ -1498,12 +1498,29 @@ int __stdcall StdCallFunc(int n) {
// Windows specific calling convention support.
// - Can bind a __fastcall function.
// - Can bind a __stdcall function.
// - Can bind const and non-const __stdcall methods.
TEST_F(BindTest, WindowsCallingConventions) {
RepeatingCallback<int()> fastcall_cb = BindRepeating(&FastCallFunc, 1);
auto fastcall_cb = BindRepeating(&FastCallFunc, 1);
EXPECT_EQ(1, fastcall_cb.Run());
RepeatingCallback<int()> stdcall_cb = BindRepeating(&StdCallFunc, 2);
auto stdcall_cb = BindRepeating(&StdCallFunc, 2);
EXPECT_EQ(2, stdcall_cb.Run());
class MethodHolder {
public:
int __stdcall Func(int n) { return n; }
int __stdcall ConstFunc(int n) const { return -n; }
};
MethodHolder obj;
auto stdcall_method_cb =
BindRepeating(&MethodHolder::Func, base::Unretained(&obj), 1);
EXPECT_EQ(1, stdcall_method_cb.Run());
const MethodHolder const_obj;
auto stdcall_const_method_cb =
BindRepeating(&MethodHolder::ConstFunc, base::Unretained(&const_obj), 1);
EXPECT_EQ(-1, stdcall_const_method_cb.Run());
}
#endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment