English 中文(简体)
C++中的功能动脉?
原标题:Function hooking in C++?
  • 时间:2011-10-12 17:03:04
  •  标签:
  • c++

在“玩笑”之后,我指的是非侵扰性地超越职能行为的能力。 一些实例:

  • Print a log message before and/or after the function body.
  • Wrap the function body in a try catch body.
  • Measure duration of a function
  • etc...

I have seen different implementations in various programming languages and libraries:

  • Aspect Oriented Programming
  • JavaScript s first class functions
  • OOP decorator pattern
  • WinAPI subclassing
  • Ruby s method_missing
  • SWIG s %exception keyword which is meant to wrap all functions in a try/catch block can be (ab)used for the purpose of hooking

我的问题是:

  • IMO this is such an incredibly useful feature that I wonder why it has never been implemented as a C++ language feature. Are there any reasons that prevent this from being made possible?
  • What are some recommended techniques or libraries to implement this in a C++ program?
最佳回答

如果你在不改变职能机构之前或之后再谈论导致采用新方法,那么你可以将其建立在上,后者使用习惯commd_ptr来启动后人功能。 不能用于<条码>/海床<>/条码>,因为之前和之后都需要利用这一技术单独运作。

此外,以下版本使用<代码>共享_ptr,但与C++11号文件,你应能够使用<代码>unique_ptr<>code>,以便在每次使用时不产生和摧毁共用点的成本的情况下,取得同样的效果。

#include <iostream>
#include <boost/chrono/chrono.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/shared_ptr.hpp>

template <typename T, typename Derived>
class base_wrapper
{
protected:
  typedef T wrapped_type;

  Derived* self() {
    return static_cast<Derived*>(this);
  }

  wrapped_type* p;

  struct suffix_wrapper
  {
    Derived* d;
    suffix_wrapper(Derived* d): d(d) {};
    void operator()(wrapped_type* p)
    {
      d->suffix(p);
    }
  };
public:
  explicit base_wrapper(wrapped_type* p) :  p(p) {};


  void prefix(wrapped_type* p) {
     // Default does nothing
  };

  void suffix(wrapped_type* p) {
     // Default does nothing
  }

  boost::shared_ptr<wrapped_type> operator->() 
  {
    self()->prefix(p);
    return boost::shared_ptr<wrapped_type>(p,suffix_wrapper(self()));
  }
};




template<typename T>
class timing_wrapper : public base_wrapper< T, timing_wrapper<T> >
{
  typedef  base_wrapper< T, timing_wrapper<T> > base;
  typedef boost::chrono::time_point<boost::chrono::system_clock, boost::chrono::duration<double> > time_point;

  time_point begin;
public:
  timing_wrapper(T* p): base(p) {}


  void prefix(T* p) 
  {
    begin = boost::chrono::system_clock::now();
  }

  void suffix(T* p)
  {
    time_point end = boost::chrono::system_clock::now();

    std::cout << "Time: " << (end-begin).count() << std::endl;
  }
};

template <typename T>
class logging_wrapper : public base_wrapper< T, logging_wrapper<T> >
{
  typedef  base_wrapper< T, logging_wrapper<T> > base;
public:
  logging_wrapper(T* p): base(p) {}

  void prefix(T* p) 
  {
    std::cout << "entering" << std::endl;
  }

  void suffix(T* p) 
  {
    std::cout << "exiting" << std::endl;
  }

};


template <template <typename> class wrapper, typename T> 
wrapper<T> make_wrapper(T* p) 
{
  return wrapper<T>(p);
}


class X 
{
public:
  void f()  const
  {
    sleep(1);
  }

  void g() const
  {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }

};



int main () {

  X x1;


  make_wrapper<timing_wrapper>(&x1)->f();

  make_wrapper<logging_wrapper>(&x1)->g();
  return 0;
}
问题回答

回答你的第一个问题:

  • Most dynamic languages have their method_missing constructs, PHP has a magic methods (__call and __callStatic) and Python has __getattr__. I think the reason this isn t available in C++ that it goes against the typed nature of C++. Implementing this on a class means that any typos will end up calling this function (at runtime!), which prevents catching these problems at compile time. Mixing C++ with duck typing doesn t seem to be a good idea.
  • C++ tries to be as fast as possible, so first class functions are out of question.
  • AOP. Now this is more interesting, techincally there s nothing that prevents this being added to the C++ standard (apart from the fact that adding another layer of complexity to an already extremly complex standard is might not be a good idea). In fact there are compilers which are able to wave code, AspectC++ is one of them. A year ago or so it wasn t stable but it looks like since then their managed to release 1.0 with a pretty decent test suite so it might does the job now.

这里有一个相关问题:

https://stackover flows.com/问题662290/emulating-clos- prior-and-a Round-in-c662774”

海事组织是一个令人信服的有益特征,因此它不是一个C++语言特征? 是否有理由阻止这样做?

C++ 语言不提供任何直接手段。 然而,它也没有对此构成任何直接限制。 这种特点比本地法典更容易使用译员,因为这一解释是一种软件,而不是一个CPU的机器指令。 如果你想要的话,你可以向C++提供一名口译员,支持她们。

问题在于why人使用C++。 许多人正在使用C++,因为他们希望执行速度加快。 为了实现这一目标,汇编者在操作系统中制作了本地法典,其格式比较可取,试图硬性编码,因为汇编的可起诉档案中有许多内容。 最后一个部分通常是指汇编/链接时间的计算地址。 如果你当时确定职能地址(或更糟糕的是,在职能机构内),那么就不再支持hoo。

尽管如此,are<>/em> 如何使hoo光价格低廉,但需要汇编推广,而且完全不可行。 雷蒙·陈 b在Windows Alan上安装了信号。 他还建议不将其用于常规法典。

This is not a C++ thing, but to accomplish some of things you mention, I have used the LD_PRELOAD environment variable in *nix systems. A good example of this technique in action is the faketime library that hooks into the time functions.

至少,在设计阶段,我使用的是一套纯虚拟课程。

class RunManager;
class PhysicsManager;
// ...

其中每项行动都界定了一套行动。

void PreRunAction();
void RunStartAction()
void RunStopAction();
void PostRunAction();

后者是国家收养机构,但使用者在从父母阶层衍生出的情况下可以凌驾。

如果附有有条件的汇编(即,我知道Yuk>/em>),你可以获取你想要的东西。

  1. There has to be a way to implement the functionality without affecting the performance of code that doesn t use the functionality. C++ is designed on the principle that you only pay performance costs for the features you use. Inserting if checks in every function to check if its been overridden would be unacceptably slow for many C++ projects. In particular, making it work so that there s no performance cost while still allowing for independent compilation of the overridden and overriding functions will be tricky. If you only allow for compile time overriding, then it s easier to do performantly (the linker can take care of overwriting addresses), but you re comparing to ruby and javascript which let you change these things at runtime.

  2. 因为它会破坏类型系统。 如果一个人能够超越其行为,那么这种职能究竟是私人还是非虚拟的?

  3. 可读性将受到极大影响。 任何职能都可能使其行为凌驾于《刑法》的其他地方! 你们需要了解什么职能,越是越是越大的法典基础。 Hooking is a bug, not a norm。 至少如果能够读一下你几个月后写的话,就是一项要求。





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签