草庐IT

c++ - 指向类成员函数的函数指针问题

coder 2024-02-10 原文

首先,我不得不承认我的编程技能非常有限,我接手了一个(非常小的)现有的 C++ OOP 项目,我试图在其中加入我自己的东西。不幸的是,我遇到了一个超出范围的问题我的知识,我希望能在这里找到一些帮助。我正在使用第三方库(无法更改)从相机中抓取图像,并将在此处使用一些占位符名称。

第三方库有一个函数“ThirdPartyGrab”来开始连续的实时抓取,并获取一个指向函数的指针,每次新帧到达时都会调用该函数。所以在一个普通的 C 应用程序中它是这样的:

ThirdPartyGrab (HookFunction);

“HookFunction”需要声明为:

long _stdcall HookFunction (long, long, void*);

或声明为“BUF_HOOK_FUNCTION_PTR”

typedef long (_stdcall *HOOK_FUNCTION_PTR) (long, long, void*);

现在我有一个 C++ 应用程序和一个类“MyFrameGrabber”,它应该封装我所做的一切。所以我像这样将钩子(Hook)函数作为私有(private)成员放入:

long _stdcall HookFunction (long, long, void*);

我的类中还有一个 public void 函数“StartGrab”,它应该启动 Grab。在里面我试着打电话:

ThirdPartyGrab (..., HookFunction, ...);

这(不足为奇)失败了。它说对 MyFrameGrabber::HookFunction 的函数调用缺少参数列表,我应该尝试使用 &MyFrameGrabber::HookFunction 来创建一个指针。但是,传递“&MyFrameGrabber::HookFunction”反而会导致另一个错误,即无法将其转换为 BUF_HOOK_FUNCTION_PTR。

看完C++ FAQ function pointers之后我想我理解这个问题,但无法提出解决方案。我试图使 Hook 函数静态化,但这也会导致转换错误。我也想过将钩子(Hook)函数放在类之外,但我需要在钩子(Hook)函数内部使用类函数。还有其他方法还是我需要改变我的整个概念?

编辑 14.01.08: 我测试了单例解决方法,因为我无法更改第三方库并且 void 指针仅适用于 Hook 函数内部使用的数据。不幸的是,它并没有像我希望的那样开箱即用....我不知道静态函数是否需要在一个单独的类中,所以我把它放在我的“MyFrameGrabber”类中:

static MyFrameGrabber& instance()
{
        static MyFrameGrabber _instance;
        return _instance;
}
long Hook(long, long, void*); // Implementation is in a separate cpp file

在我的 cpp 文件中,我有 call_hook 函数:

long MFTYPE call_hook(long x, MIL_ID y, void MPTYPE *z)
{
    return MyFrameGrabber::instance().Hook(x,y,z);
}
void
MyFrameGrabber::grab ()
{
    ThirdPartyGrab(..., call_hook, ...);
}

但这在 static MatroxFrameGrabber _instance; 中给我一个错误,没有找到匹配的标准构造函数。这是正确的,因为我的 MyFrameGrabber 构造函数如下所示:

MyFrameGrabber (void* x,
                const std::string &y, int z,
                std::string &zz);

我试图放入一个空的构造函数 MyFrameGrabber(); 但这会导致链接器错误。我应该将空参数传递给单例中的 MyFrameGrabber 构造函数吗?或者我是否需要一个单独的 Hook 类,如果是,我如何访问 MyFrameGrabber 函数?提前致谢。

第二次编辑 15.01.08: 我应用了更改,它现在可以编译和链接。不幸的是,我还不能在运行时对此进行测试,因为它是一个 DLL,而且我还没有 Debug Caller Exe,并且在初始化等过程中还有其他问题。我会将帖子标记为答案,因为我确信这是执行此操作的正确方法。

最佳答案

您的私有(private)成员方法有一个隐含的 this 指针作为第一个参数。如果你把它写出来,很明显函数签名不匹配。

您需要编写一个静态成员函数,它可以作为回调函数传递给库。 HookFunction 的最后一个参数,一个 void*,在我看来非常像一个 cookie,可以在其中传递自己的指针。

所以,总而言之,它应该是这样的:

class MyClass {
  long MyCallback(long, long) {
    // implement your callback code here
  }

  static long __stdcall ThirdPartyGrabCallback(long a, long b, void* self) {
    return reinterpret_cast<MyClass*>(self)->MyCallback(a, b);
  }
public:
  void StartGrab() {
    ThirdPartyGrab(..., &MyClass::ThirdPartyGrabCallback, ..., this, ...);
  }
};

这当然只有在 void* 参数按我说的做时才有效。 thisThirdPartyGrab() 调用中的位置在具有完整的函数签名(包括可用的参数名称)时应该很容易找到。

关于c++ - 指向类成员函数的函数指针问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/439540/

有关c++ - 指向类成员函数的函数指针问题的更多相关文章

  1. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

  2. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  5. ruby - 通过 RVM (OSX Mountain Lion) 安装 Ruby 2.0.0-p247 时遇到问题 - 2

    我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search

  6. ruby - Fast-stemmer 安装问题 - 2

    由于fast-stemmer的问题,我很难安装我想要的任何ruby​​gem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=

  7. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  8. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

  9. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  10. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

随机推荐