Class function callback

[DV]一種對具有互相粘連功能的Register的驗證方案 --- Register Callback 本文提出了一种针对具有粘性功能的寄存器(Register)的验证方案。通过UVM回调机制实现对寄存器set、clear和mask功能的验证。主要方法包括:1) 定义继承自uvm_reg_cbs的set_regs_callback、clr_regs_callback等回调类,在post_predict函数中更新mirror value;2) 在test_base中实现append_field_callback函数将需要验证的寄存器字段注册到回调池;3) 在run_phase调用update_cirq_reg_ 阅读详情

这篇文章介绍了如何使类中的非静态成员函数成为线程函数或者使其成为回调函数的方法,颇值得一读:

Introduction

In this article I'll show you how to make a callback to a function within a class that is NOT static. This will make use of functions, pointers and some assembly. It's not possible to my knowledge to do this without the ASM. However, this guide does not require you to know any ASM; instead it will explain what it does. This guide is not intended to teach out ASM, however. There's plenty of other good guides out there on the web for that. This is an advanced technique, however, but even beginners should be able to make use of it.

What do we need? A compiler that can do ASM and a class! In this article I will also show you how I used this technique to forward messages through a window proc. Let's get started then!

First then, we need a base-class. I use MFC in this sample to show you how this technique works. So if you want to follow in this sample, use MFC to create a dialog window. The class is the dialog class of your main window.

class CMyTestDlg
{
  public:
    ...
    CProcEdit m_MyEdit;
  protected:
    LRESULT WindowProc(CWnd* pCtrl, UINT message, WPARAM wParam, LPARAM lParam);
};

Perhaps you noticed the WindowProc isn't virtual plus an extra argument: pCtrl. This is because, in this example, I intend to make this a "global" WindowProc. All controls will forward messages to this one, kinda like the original window proc (non-MFC).

Now that we have this, we need to create the whole forwarding function. How? It's quite simple. We simply derive the controls you want to forward messages from with a new class. Let's define this one, too...

typedef LRESULT (WndProcPtr)(UINT,WPARAM,LPARAM);

class CProcEdit: public CEdit
{
  public:
    struct CallbackPtr
    {
      CWnd* pThisPtr;
      WndProcPtr* pWndProcPtr;
    } pCallbackPtr;
  protected:
     virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
};

We don't need any more complex class. It inherits everything from MFCs CEdit class, their edit class. In any case, this class' purpose is only to forward its messages. That's why we override the WindowProc. You're probably also wondering why the struct and two arguments? A function pointer is only one variable. Yes... but we need two arguments: one for the address to the function and one pointing to the class itself that contains this function. Got that? Good. As to why we need the second... let me get back to that later.

Now then, to make it able to do a callback, we must set these variables when initializing (or creating) the dialog or class. So we do this in the InitDialog of our main dialog. Now also comes the first part where we must use assembly. Let me show you the code first and then discuss what it does...

BOOL CMyTestDlg::OnInitDialog()
{
  WndProcPtr* pCallback;
  __asm
  {
    mov eax, WindowProc;
    mov pCallback, eax;
  };
  m_MyEdit.pCallbackPtr.pThisPtr = this;
  m_MyEdit.pCallbackPtr.pWndProcPtr = pCallback;
};

That's all. Now let's see what this code does... and why the ASM? ...and what does it do, the ASM? Let me explain... if you're experienced with this, you should know that...

pCallback = WindowProc;

...will give a compile error. That's why we must use assembly! There is no such restriction there. The "mov" opcode moves database from or to memory. So first, we move the offset of the WindowProc function into the eax register. And then we move the contents of the eax register into out pCallback variable. Note that we cannot move the contents directly into the variable due to restrictions of the ASM language. After this, the pCallback variable contains the address (or offset) of our function. So then we set the two variables of the edit class to point to our dialog class and the function. Okay, with me so far? I hope you are!

Now that we've initialized the class, we must make sure the edit class forwards out messages. This might be a little tricky... Anyway, here's the code:

LRESULT CProcEdit::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
  if (pWndProc) 
  {
    __asm
    { 
      // Pass arguments (right to left)
      mov eax, [lParam];
      push eax;
      mov eax, [wParam];
      push eax;
      mov eax, [message];
      push eax;
      mov eax, this;
      push eax;

      // Fill ecx with the class placement
      mov eax, this;
      add eax, pThisPtr;
      mov ecx, [eax];

     // Call function
     mov eax, pWndProc;
     add eax, this;
     mov eax, [eax];
     call eax;
    }
  }
  return CEdit::WindowProc(message, wParam, lParam);
}

Whew, that was sure a lot of assembly code. What does it do? Why do we need ASM to call a function pointer? Well, it's not as easy as you think... first, let me tell you why a normal call wouldn't work. As you know, in classes there is a "this" pointer. The "this" pointer is stored in the ecx register. The ecx register must point to the offset where the class is located. What happens then, if we call the function normally? The offset placed in ecx is the offset of the current class - or in other words the CProcEdit class! When this happens, the function we call won't be able to access its member correctly, possibly even creating a access violation. Why does this happen? The functions are in the classes, so... why can't you just call them and it works?

Good question... unfortunately, it doesn't work that way... did you ever export a function in a DLL that is part of a class? It works. But when you call them, the this pointer is NULL! Why? That's because functions are not stored in the classes! Look at this class...

class CAnotherClass
{
  int arg1;
  int arg2;
  void myfunc() { }
};

A sizeof on this class will return 8! Because there are two int arguments. The functions are NOT counted! So... when calling a function within a class, the function must know where the class exists in order to reach its data. That's why there is a this pointer, which is stored in the ecx register.

That is why we need to assembly. We need to make sure, we fill the ecx register properly. Hence, why we also took a pointer to the class itself. Okay then, what does the code do? Let's see here...

First, we push the arguments onto the stack. To push something onto the stack, we need to put them into a register first. All arguments are passed from right to left, so there. Second, we must fill in the ecx with the address (or offset) of its class! And thirdly, we call the function. How all this works, I'm not going to explain more detailed... if you wish to know, then go find an ASM course.

Lastly, we call the base class' windowproc function so that it may further handle the messages. This is all we need to do! There is one note on this example I wish to pass on, however. In the called windowproc of CMyTestDlg, do not call the base class's window proc function! Why? Because the messages are not intended for that class. If you do pass them along, you'll probably get weird painting on the form and other strange things. Instead, return 0 or some other value; it doesn't matter since we do not return the value returned by this window proc.

...And that's all folks! Now you can probably understand why callback to class functions aren't possible. And if not... I guess I can spoil it to you. It's simple. The compiler does not know to which class the function belongs.

Happy programming! 

深入解析uncompyle6反编译pyc文件及常见错误修复指南 本文深入解析了使用uncompyle6工具反编译Python字节码文件(.pyc)的完整流程。针对实践中最高频的KeyError和Python版本范围限制两大错误,提供了详细的修复方案与步骤指南,并分享了处理复杂反编译结果的高级技巧与安全实践,是进行代码恢复、调试与分析的重要参考。 阅读详情

相关推荐

基于YOLO11的垃圾分类AI模型训练实战

通过这次实战,我们成功训练出了一个高性能的垃圾分类AI模型。项目展示了从数据准备、模型训练到结果分析的完整流程,为AI在环保领域的应用提供了有价值的参考。项目文件结构│ ├── best.pt # 最佳模型权重│ └── last.pt # 最新模型权重├── results.csv # 详细训练数据├── results.png # 训练曲线图├── confusion_matrix.png # 混淆矩阵└── args.yaml # 训练参数配置。

lydz1的博客 1657

3D MAX脚本原理

为什么要学习3D MAX脚本? 3D MAX Script是我迄今为止见过编程语言最自由的一种脚本开源环境,他的自由程度远远超过了Sun 的JAVA,她没有大小写的区分,以及固定的公式和程序工作流程树,MAX Script一旦被编写,人们就可以从任何一行进行代码的编译,不需要符合格式的束缚。而且MAX Script的功能相当强大。 详细的说明一下MAX Script功能到底有多强大:MAX S

痞子龙3D编程 2万+

整车CAN网络错误帧排查方法

本文围绕 CAN 总线错误帧展开,先剖析其产生原因,涵盖物理连接与硬件问题、电磁兼容性问题、总线负载与设计问题及配置问题;再阐述位错误、填充错误等 5 类错误帧类型;接着说明错误帧与总线 BUSOFF 的关系,解析主动 / 被动错误状态及 BUSOFF 的触发与恢复;还结合整车故障案例做实际分析,指出错误帧根源多为线束或控制器问题。最后总结,强调错误帧是 CAN 协议保障高鲁棒性的机制,掌握相关知识助工程师提升 CAN 网络处理能力。

车载网络小D的博客 1246

learn go function callback

package main // 参考文档: // https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/06.7.md import ( "fmt" ) func main () { callback(1, Add) } func Add(a, b int) {...

weixin_34220834的博客 115

Frida提取Cocos游戏XXTEA密钥的实战方法论

XXTEA是一种轻量级分组加密算法,广泛用于移动端游戏通信保护;其128位密钥的安全性直接决定网络协议逆向成败。在Cocos引擎生态中,密钥常以静态常量、JNI动态传递或Native运行时派生三种形态存在,导致传统静态分析失效。Frida凭借跨Java/Native注入能力与内存实时观测优势,成为捕获密钥‘出生瞬间’的关键工具——尤其适用于hook xxtea_encrypt函数入口、监控JNI参数传递、设置内存断点追踪派生过程等场景。本文聚焦Cocos2d-x与Cocos Creator项目,覆盖从密钥识

weixin_33509600的博客 416

Matplotlib之bar3d画3D柱状图

3D柱状图通常用于展示数据集中不同分类项的数据大小或数量。与普通的柱状图相比,3D柱状图更适合展示数据的三个维度 3D 柱状图 按行/列涂颜色 柱加阴影、描黑边 自定义座标轴名、刻度标签、范围

我走的每一步都算数 1121

model过拟合,使用callback函数根据loss值来提前终止训练

以下代码均在jupyterlab里面实现 # 添加注释 %config IPComplter.greedy=True # 导入库 import os import numpy as np # 读写gzip文件的时候需要使用到gzip模块 import gzip # 导入本地数据集 def load_data(data_floder): ## 获取文件的路径 filesname = ['train-labels-idx1-ubyte.gz' , 'train-images-idx3-uby

yky__xukai的博客 1885

【转录调控网络】代谢组学与其他组学的联合分析经典模式简介

多组学联合分析经典模式转录组学&代谢组学联合分析 转录组学&代谢组学联合分析 转录组是获得生物体内基因表达的重要方法,代谢组是生物体表型的基础和直接体现者。 转录组测序可以得到大量差异表达基因和调控代谢通路,但由于基因与表型之间很难之间关联,导致关键的信号通路难以确定,因此往往达不到预期的研究目的。代谢产物是生物体在内外调控下基因转录的最终结果,是生物体表型的物质基础。 在系统生物学研究时代,生物过程复杂多变,基因调控网络复杂。针对特定的生理、病理等表型进行研究,利用转录组的数据获得大量差异

小哲的博客 6193

Error: Call to undefined function _()

Notice that our view action takes a parameter: the ID of the post we’d like to see. This parameter is handed to the action through the requested URL. If a user requests /posts/view/3, then the value

zhaoyingjiao的专栏 2391

Python 爬虫实战:在丁香医生抓取健康科普文章阅读量,普及健康知识

requests:用于发送 HTTP 请求,获取网页内容。或 lxml:用于解析 HTML 页面,提取目标数据。pandas:用于数据清洗和分析。matplotlib和seaborn:用于数据可视化。通过本项目,我们实现了以下目标:使用 Python 爬虫抓取丁香医生的健康科普文章阅读量。对数据进行清洗和分析,找出热门文章。通过可视化展示数据,并普及健康知识。

u014481728的博客 1566

Spring Boot 与 Redisson 版本适配深度解析

Spring Boot 与 Redisson 的版本适配是一个动态演进的过程。开发者需要密切关注两者官方的版本更新日志,建立完善的版本验证机制。本文提供的适配方案基于当前最新技术状态(2024年1月),建议在实际生产环境中通过灰度发布策略验证版本兼容性。只有深入理解底层技术原理,才能在分布式系统的星辰大海中稳健航行。延伸阅读Spring Boot 官方迁移指南。

fudaihb的博客 1080

callback 在满足要求时停止迭代

class myCallback(tf.keras.callbacks.Callback): def on_epoch_end(self, epoch, logs={}): if(logs.get('accuracy')>0.6): print("\nReached 60% accuracy so cancelling training!") self.model.stop_training = True mnist = tf.keras.datasets.fa.

kimyu_的博客 287

这才是 Python 的正确玩法!用强化学习 (RL) 训练 AI 玩《王者荣耀》,胜率 90%!

大家打排位时,一定遇到过那种“意识神级、操作零失误”的对手,或者“走位呆滞、送人头”的队友。以前的“人机”是程序员写死的脚本(If 血量<20% Then 回城)。而现在的顶级 AI(如腾讯绝悟、OpenAI Five),是靠强化学习 (Reinforcement Learning)自己“左右互搏”练出来的。今天,我们不谈枯燥的数学公式,我将手把手教你用,搭建一个能玩 MOBA 游戏的 AI Agent。即使不能去 KPL 打职业,虐一下钻石局还是绰绰有余的!

BUG猿的博客 1182

What‘s this in a class method and in a callback function?

【代码】What‘s this in a class method and in a callback function?

一名高级工程师的博客 246

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

AJAX技术(二)common class

/*  Prototype JavaScript framework, version 1.3.1*  (c) 2005 Sam Stephenson **  THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff*  against the source tree, available from the Pr

minsky的专栏 1130

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

将对象转为数组方法:延伸array_map函数在PHP类中调用内部方法

    public static function objectToArray($d) { if (is_object($d)) { $d = get_object_vars($d); } if (is_array($d)) { //数组中的...

weixin_30652879的博客 75

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Keras 常用callback function

TensorBoard通过结合TF的TensorBoard将网络结构以及运行时状态可视化from keras.callbacks import TensorBoardmodel.fit([encoder_input_data, decoder_input_data], decoder_target_data,          batch_size=batch_size,          epo...

2186

php callback function 调用的几种姿势

搬砖时遇到的一点点关于回调函数(callback function)的总结。 一般函数 $this->callSomeFunction('some_global_php_function'); 对象实例方法 // Only from inside the same class $this->callSomeFunction([$this, 'myCallback']); /...

don6105的技术笔记 1898

uvm_callback机制学习总结

UVM中的Callback机制解析:从原理到实践 摘要: 本文系统解析了UVM验证方法学中的Callback机制。首先介绍了Callback的基本概念,它是一种设计模式,允许在不修改原有代码的情况下动态注入或修改行为。在UVM验证环境中,Callback机制主要实现了四大功能:动态错误注入、组件解耦与重用、测试行为动态定制以及事务级监控。文章详细阐述了纯SystemVerilog和UVM两种环境下的实现方式,重点分析了UVM中的核心类和宏(uvm_callback、uvm_callbacks#(T,CB)、

IC验证及芯片SOC知识分享 578

如何让AI真正理解你的需求

而且是纯粹的那种,不要框架,只依赖原生。早期 JavaScript 没有类的概念,通过 “构造函数+原型链” 模拟面向对象,this 因“动态绑定”特性,从强类型语言的角度看,其表现堪比怪物,this 指向完全依赖调用方式,稍不注意就出错。继承的先父后子,无论是隐式调用父类无参构造,还是显式调用有参构造,父类的构造函数总是先执行,父类成员先行完成初始化,不会出现子类访问未就绪的父类属性的情况。JavaScript 的 this 像怪物,核心是指向由函数调用时的方式决定,属于动态绑定,而非定义时的静态绑定。

wensan188的博客 313

Callback function与if-then-else

对function pointer的应用可以大致看出一个程序员对C的理解和驾驭能力。用function pointer甚至可以实现一部分OO才有的polymorphism,但钟情于使用function pointer会使程序的静态分析变得难以下手;类似于C++,过多的object互相纠缠,导致程序的运行期行为异常复杂。这时候,对程序的debug从流程切换到了单个class,从function ca

noproblem_jyb的专栏 880

chromium的base源码阅读之Callback一

简介 本文描述下chromium使用base库中的callback,相关代码位于base库的根目录下的callback及callback相关,bind及bind相关的,本系列本人只是简单说一下自己的感受,有些存在的问题还望大家一块讨论。 相关base库timer讲解可参考 chromium的base源码阅读之Timer. callback是chromium自己封装的回调函数,需要配合bind使用,...

leapmotion的博客 1249

[开发故事]第四回:应用反射在运行时动态获取类型信息

而且是纯粹的那种,不要框架,只依赖原生。早期 JavaScript 没有类的概念,通过 “构造函数+原型链” 模拟面向对象,this 因“动态绑定”特性,从强类型语言的角度看,其表现堪比怪物,this 指向完全依赖调用方式,稍不注意就出错。继承的先父后子,无论是隐式调用父类无参构造,还是显式调用有参构造,父类的构造函数总是先执行,父类成员先行完成初始化,不会出现子类访问未就绪的父类属性的情况。JavaScript 的 this 像怪物,核心是指向由函数调用时的方式决定,属于动态绑定,而非定义时的静态绑定。

ascagasegsh的博客 706

JS中的 回调函数(callback)

回调函数是一段可执行的代码段,它作为一个参数传递给其他的代码,其作用是在需要的时候方便调用这段(回调函数)代码。(作为参数传递到另外一个函数中,这个作为参数的函数就是回调函数)原文链接:https://blog.youkuaiyun.com/weixin_47075145/article/details/125752446。把函数当作一个参数传到另外一个函数中,当需要用这个函数是,再回调运行()这个函数.理解:函数可以作为一个参数传递到另外一个函数中。1.什么是回调函数(callback)呢?

fsd1112的博客 146

chromium的base源码阅读一 callback的使用

简介 本文描述下chromium使用base库中的callback,相关代码位于base库的根目录下的callback及cal...

sway913的博客 1236

如何设计通用的回调机制

如何设计通用的回调机制许多程序都需要一种通用的回调机制,这种回调机制不用关心它们的类类型。例如,一个调用GUI组件成员函数的事件驱动的系统中,调用之前并不知道实际的类型信息。这时可以创建一种通用的回调类模板将这种任务流程化。该模板第一个参数是其成员函数被调用的类,第二个模板参数是一个指针,指向类的成员函数。这里的关键技巧第二个参数基于(或者说依赖于)第一个参数: template

小发猫 1424
上一篇: typedef的四个用途和两个陷阱
下一篇: Use Pseudoregisters to debug in MSVC++
undefined_behavior
博客等级 码龄19年 1粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值