From 828a1b7cfeb2a63aae407428782e90d419e692e6 Mon Sep 17 00:00:00 2001 From: Zhang Yu Date: Mon, 30 Nov 2020 20:37:03 +0800 Subject: [PATCH] =?UTF-8?q?Feat=20=E6=94=AF=E6=8C=81=E6=97=A0=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E7=9A=84lamda=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 支持无参数的lamda函数 修改使用说明 调整代码格式 --- README.md | 92 ++++++++++++++++++++++++++++++++++++++---- stub-ext/stub-shadow.h | 49 +++++++++++++++++----- stub-ext/stubext.h | 2 +- 3 files changed, 126 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 4d4150c..1d80f81 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,16 @@ # 使用说明 ## 使用`lamda`函数打桩 使用`lamda`函数作为打桩函数,需调专用接口`StubExt::set_lamda`。 -**注意**:`lamda`函数的参数列表必须与被打桩的函数参数一致,如果被打桩的函数时类的成员函数,`lamda`函数的第一参数必须为该类的指针,接着是该成员函数的参数列表。 + +`lamda`函数可以使用参数和无参数: + +1. 为常规函数打桩,`lamda`有参数时`lamda`函数的参数列表必须与被打桩的函数参数一致。 +2. 为成员函数打桩,`lamda`有参数时`lamda`函数的第一个参数必须为该类的指针,接着是该成员函数的参数列表。 +3. 为常规函数打桩,`lamda`无参数可直接使用。 +4. 为成员函数打桩,`lamda`无参数可直接使用。 ### 示列 -- 为常规函数打桩 +- 为常规函数打桩,使用参数 ```c++ #include "stubext.h" using namespace stub_ext; @@ -40,8 +46,28 @@ int main(int argc, char *argv[]) return 0; } ``` +- 为常规函数打桩,不使用参数 +```c++ +#include "stubext.h" +using namespace stub_ext; -- 为成员函数打桩 +int test(){return 0;} +int ret_test(int a){return a;} +static int add_test(int a ,int b){return a + b;} +int main(int argc, char *argv[]) +{ + int dd = -1; + StubExt st; + st.set_lamda(&test,[&dd](){dd = 9;return dd;}); + st.set_lamda(&ret_test,[&dd](){dd = 9;return dd;}); + st.set_lamda(&add_test,[&dd](){dd = 9;return dd;}); + int r1 = test(); + int r2 = ret_test(2); + int r2 = add_test(1,2); + return 0; +} +``` +- 为成员函数打桩,使用参数 ```c++ #include "stubext.h" using namespace stub_ext; @@ -61,8 +87,8 @@ int main(int argc, char *argv[]) int dd = -1; StubExt st; st.set_lamda(ADDR(Test,test),[&dd](Test *t){dd = 5; return dd;}); - st.set_lamda(ADDR(Test,ret_test),[&dd](Test*,int a){dd = 5 + a;return dd;}); - st.set_lamda(ADDR(Test,add_test),[&dd](Test*,int a, int b){dd = 5 + a - b;return dd;}); + st.set_lamda(ADDR(Test,ret_test),[&dd](Test*,int a){dd = 5 + a; return dd;}); + st.set_lamda(ADDR(Test,add_test),[&dd](Test*,int a, int b){dd = 5 + a - b; return dd;}); Test t; int r1 = t.test(); @@ -71,8 +97,60 @@ int main(int argc, char *argv[]) return 0; } ``` +- 为成员函数打桩,不使用参数 +```c++ +#include "stubext.h" +using namespace stub_ext; + +class Test +{ +public: + int test(){return m;} + int ret_test(int a){return m + a;} + int add_test(int a ,int b) {return m + a + b;} +private: + int m = 1; +}; -- 为类中的静态函数打桩 +int main(int argc, char *argv[]) +{ + int dd = -1; + StubExt st; + st.set_lamda(ADDR(Test,test),[&dd](){dd = 5; return dd;}); + st.set_lamda(ADDR(Test,ret_test),[&dd](){dd = 5; return dd;}); + st.set_lamda(ADDR(Test,add_test),[&dd](){dd = 5; return dd;}); + + Test t; + int r1 = t.test(); + int r2 = t.ret_test(2); + int r2 = t.add_test(1,2); + return 0; +} +``` +- 为类中的静态函数打桩,使用参数 +```c++ +#include "stubext.h" +using namespace stub_ext; + +class Test +{ +public: + static int sub_test(int a ,int b) {return a - b;} +}; + +int main(int argc, char *argv[]) +{ + int dd = -1; + StubExt st; + st.set_lamda(ADDR(Test,sub_test),[&dd](int a, int b){dd = 5 - a - b; return dd;}); + + Test t; + int r1 = t.sub_test(1,2); + int r2 = Test::sub_test(1,2); + return 0; +} +``` +- 为类中的静态函数打桩,不使用参数 ```c++ #include "stubext.h" using namespace stub_ext; @@ -87,7 +165,7 @@ int main(int argc, char *argv[]) { int dd = -1; StubExt st; - st.set_lamda(ADDR(Test,sub_test),[&dd](int a, int b){dd = 5 - a - b;return dd;}); + st.set_lamda(ADDR(Test,sub_test),[&dd](){dd = 5; return dd;}); Test t; int r1 = t.sub_test(1,2); diff --git a/stub-ext/stub-shadow.h b/stub-ext/stub-shadow.h index 0081a5e..523244a 100644 --- a/stub-ext/stub-shadow.h +++ b/stub-ext/stub-shadow.h @@ -31,6 +31,9 @@ #include namespace stub_ext { + +#define LAMDA_FUNCTION_TYPE decltype(&Lamda::operator()) + class Wrapper { public: @@ -38,29 +41,57 @@ public: virtual ~Wrapper(){} }; -template +template class LamdaWrapper : public Wrapper { public: LamdaWrapper(Lamda func): Wrapper(),_func(func){} ~LamdaWrapper(){} - Lamda _func; }; + +template +struct LamdaCaller +{ + +}; + +template +struct LamdaCaller +{ + template + static Ret call(LamdaWrapper *wrapper, OrgArgs... args) + { + return wrapper->_func(args...); + } +}; + +template +struct LamdaCaller +{ + template + static Ret call(LamdaWrapper *wrapper, OrgArgs... args) + { + return wrapper->_func(); + } +}; + + static std::unordered_map stub_wrappers; -template +template struct FuncShadow { }; -template +template struct FuncShadow { typedef Ret (*Shadow)(Args...); typedef Ret RetType; + static Ret call(Args ...args) { Shadow shadow = &call; @@ -68,11 +99,11 @@ struct FuncShadow auto iter = stub_wrappers.find(id); assert(stub_wrappers.find(id) != stub_wrappers.end()); LamdaWrapper *wrapper = dynamic_cast *>(iter->second); - return wrapper->_func(args...); + return LamdaCaller::call(wrapper, args...); } }; -template +template struct FuncShadow { typedef Ret (*Shadow)(Obj *,Args...); @@ -84,12 +115,12 @@ struct FuncShadow auto iter = stub_wrappers.find(id); assert(stub_wrappers.find(id) != stub_wrappers.end()); LamdaWrapper *wrapper = dynamic_cast *>(iter->second); - return wrapper->_func(obj,args...); + return LamdaCaller::call(wrapper, obj, args...); } }; -template -typename FuncShadow::Shadow depictShadow(Wrapper **wrapper, Func func, Lamda lamda) +template +typename FuncShadow::Shadow depictShadow(Wrapper **wrapper, Func func, Lamda lamda) { *wrapper = new LamdaWrapper(lamda); typename FuncShadow::Shadow shadow = &FuncShadow::call; diff --git a/stub-ext/stubext.h b/stub-ext/stubext.h index 23e2387..808c6a8 100644 --- a/stub-ext/stubext.h +++ b/stub-ext/stubext.h @@ -38,7 +38,7 @@ class StubExt : public Stub public: StubExt() : Stub() {} - template + template void set_lamda(T addr, Lamda lamda) { Wrapper *wrapper = nullptr; -- Gitee