2 jomoonrain2 jomoonrain2 于 2015.06.12 18:13 提问

c++通过成员函数指针 跨DLL回调的问题

最近写了个项目,里面遇到了一个函数跨模块回调的问题,由于项目本身比较复杂,所以简化了一下,但是还是能反映问题的。

问题大致是这样:
我从主程序(exe)中调用一个DLL(称为D)中的类,这个类又调用另一个DLL(称为B)中的类,在每一级的调用之前都已经传入了一个函数指针, 在B执行完之后通过回调返回到上一个DLL(D),然后再通过回调最后返回到主程序。但是在从B返回到D之后,D的数据好像变了,导致D最终无法返回主程序。

更具体一点:
D是依赖于B的,而主程序对B和D都依赖。
回调我是通过类的成员函数指针:

typedef void(Object::*CallBack)(...);

通过一个结构体来保存函数指针和该函数所属的对象。

typedef struct 
{
    Object* object;
    CallBack method;
} EventHandler;

代码片段在这里:
https://code.csdn.net/snippets/693435
项目地址:
https://code.csdn.net/jomoonrain2/c-lab

我觉得最有问题是我定义的这个函数指针。
但是问题是如果我没有跨DLL的话,貌似这样是没问题的。我知道跨模块调用应该挺复杂,虽然可以想其他的办法,但是这个问题如果搞不明白,吃饭都不香。。。

希望各路高手不嫌弃我这仅有的60币,不吝赐教。

3个回答

gamefinity
gamefinity   Rxr 2015.06.12 19:58
已采纳

在Object.h,你定义的Callback是,不限制参数个数

typedef void(Object::*CallBack)(...);

但是在实际调用的时候,你给的函数是App::onCall.App::inCall 的定义是

 void App::onCall(Derive* d)

因此这里是有矛盾的。传递的函数指针的结构不一样。
因此我把Object.h里面的CallBack定义改为:

 typedef void(Object::*CallBack)(void *p);

并且随后的两个宏业修改了

 #define EV_CB(_obj,_func) EventHandler{_obj,(CallBack)&_func}
#define EV_INVOKE(_cb,p) do{ \
        if(_cb.object && _cb.method) {\
            (_cb.object->*_cb.method)(p);\
                            }\
    }while(0)

运行可以通过,但是不知道是不是符合你的要求。

jomoonrain2
jomoonrain2 多谢,应该就是这个问题了。虽然暂时还不理解可变参数这种情况的函数指针。。喝喝,慢慢研究吧
2 年多之前 回复
devmiao
devmiao   Ds   Rxr 2015.06.12 22:16

看看你的调用约定是不是有问题,你的dll有没有用全局函数

jomoonrain2
jomoonrain2 恩 是调用约定的问题,
2 年多之前 回复
91program
91program   Ds   Rxr 2015.06.12 19:00

D的数据好像变了,导致D最终无法返回主程序。是什么意思?
在同一个EXE中,使用函数指针应该没有问题。先要判断一下,是因为数据D中的数据变化了,还是错误的使用了函数指针!

jomoonrain2
jomoonrain2 就是好像D这个对象的内存位置都变了,比如D里面原来有的变量,都变成了奇怪的值。但我从来没有改变过他们(除了初始化),各个类之间的交互就是单纯的相互调用而已。 结论应该是函数指针使用的不当,但是根本的原因还有待研究。
2 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片