[☆☆☆☆☆]void WINAPI类型的函数怎样作为class成员函数被callback?

pbMaster 2003-08-25 08:31:48
我在做网络拨号程序的时候碰到这样一个问题:
在拨号调用函数(原型定义ras.h)
DWORD APIENTRY RasDialA( LPRASDIALEXTENSIONS, LPCSTR, LPRASDIALPARAMSA, DWORD,LPVOID, LPHRASCONN );
其中第5个参数LPVOID是一个VOID WINAPI 返回的函数指针,用来被设置为callback函数,一般被申明为:
void WINAPI RasDialFunc(UINT MSG,RASCONNSTATE rasconnstate,DWORD dwError);
拨号函数的调用实例为:
int ret=RasDialA(NULL,NULL,¶ms,0,&RasDialFunc,&hrasconn);
==================================
当把callback函数void WINAPI RasDialFunc申明为全局函数时,这一切都没有问题!
==================================
但当把void WINAPI RasDialFunc申明为一个class的成员函数时,问题就出现了。
class TUDialNetwork{
public:
void __fastcall beginDial();
void WINAPI RasDialFunc(UINT MSG,RASCONNSTATE rasconnstate,DWORD dwError);
}
void WINAPI TUDialNetwork::RasDialFunc(UINT MSG,RASCONNSTATE rasconnstate,DWORD dwError){}
调用方法:
void __fastcall TUDialNetwork::beginDial()
{
int ret=RasDialA(NULL,NULL,¶ms,0,&RasDialFunc,&hrasconn);
}
编译都通不过!
=================================
哪位高手指点迷津?
...全文
190 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
pbMaster 2003-08-26
  • 打赏
  • 举报
回复
我真是老糊涂了!
这么简单的一个问题居然都搞了两天。
=====
其实,只要在PACKAGE中定义一个全局的TUDialNetwork指针,再在TUDialNetwork的构造函数中把this赋给它,这样在全局的callback函数中就可以用这个指针访问TUDialNetwork的成员了!
------------
这个组件的BCB6版本已经做好了,只要设置好参数,调用UDialNetwork1->rasDial()就可以拨号了!连接形成时会触发OnConnected事件。程序员可以在此事件中加入通讯代码。
哪位需要的给我发EMAIL:
catmiwang@hotmail.com
catmiw 2003-08-25
  • 打赏
  • 举报
回复
--keiy():
那到底有解药没有?
pbMaster 2003-08-25
  • 打赏
  • 举报
回复
--zjqyb:
已发!
柯本 2003-08-25
  • 打赏
  • 举报
回复
程序已收到:
这里有问题:
LPRasDialFunc=RasDialFunc;
int ret=RasDialA(NULL,NULL,¶ms,0,&LPRasDialFunc,&hrasconn);
LPRasDialFunc=RasDialFunc:就是指向函数的地址,再取&LPRasDialFunc址传进后没意义了
理论上就应是int ret=RasDialA(NULL,NULL,¶ms,0,LPRasDialFunc,&hrasconn);
由于__closure 不能与void *相互转换所以出错
我上面的方法对你的实现也有问题.
只能像zjqyb()那样定义一个外部函数了!
pbMaster 2003-08-25
  • 打赏
  • 举报
回复
--keiy():
已发!
柯本 2003-08-25
  • 打赏
  • 举报
回复
keiy@wx88.net
zjqyb 2003-08-25
  • 打赏
  • 举报
回复
定义一个全程实例TUDialNetwork DialNetwork;应该可以
pbMaster 2003-08-25
  • 打赏
  • 举报
回复
--zjqyb:
--keiy():
请二位DX把EMAIL留下,我传我的程序请二位看看。
===============
我的目标是这样:
做一个组件TUDialNetwork,在别人编程时,把组件放上去就可以用了。
调用UDialNetwork1->beginDial();就可以开始拨号。
在拨号完成,连接形成时(系统会在此时调用RasDialFunc),触发组件的OnConnected事件。
这样别人在OnConnected事件代码中完成远程数据交换的代码就可以了。
柯本 2003-08-25
  • 打赏
  • 举报
回复
忘了贴传实例的:

class TUDialNetwork{
public:
void __fastcall beginDial();
void WINAPI RasDialFunc(UINT MSG,RASCONNSTATE rasconnstate,DWORD dwError);
} sl ;

void __fastcall TUDialNetwork::beginDial()
{
void (M::*p)();
RASDIALPARAMS params;
HRASCONN hrasconn;
void (*p2)(TUDialNetwork &par);

int *m;
p =&M::test;
m=(int *)&p;
p2 = (void (*)(TUDialNetwork &sl)) (*m);
int ret=RasDial(NULL,NULL,¶ms,0,(LPTSTR )p2,&hrasconn);
}

sl 传给RasDial后根本不会用到!!!
柯本 2003-08-25
  • 打赏
  • 举报
回复
有一种方式试试
class TUDialNetwork{
public:
void __fastcall beginDial();
void WINAPI RasDialFunc(UINT MSG,RASCONNSTATE rasconnstate,DWORD dwError);
} ;

void __fastcall TUDialNetwork::beginDial()
{
void (M::*p)();
RASDIALPARAMS params;
HRASCONN hrasconn;

int *m;
p =&M::test;
m=(int *)&p;
int ret=RasDial(NULL,NULL,¶ms,0,(LPTSTR )(*m),&hrasconn);
}
如果要调类成员也可以
不过你把类成员传给一个API有意义吗?
pbMaster 2003-08-25
  • 打赏
  • 举报
回复
--zjqyb:
可是这样无法实现封装啊。
我是想作成一个组件的!
zjqyb 2003-08-25
  • 打赏
  • 举报
回复
你不要在类里面定义
TUDialNetwork DialNetwork;
void test(UINT MSG,RASCONNSTATE rasconnstate,DWORD dwError)
{
fp fp1= &DialNetwork.RasDialFunc;//必须带上实例DialNetwork
fp1(MSG,rasconnstate,dwError);
}
pbMaster 2003-08-25
  • 打赏
  • 举报
回复
-- zjqyb:
我try过了,编译通过但程序运行时老是出错(非法访问错)。

申明:
typedef void __fastcall(__closure *fp)(UINT,RASCONNSTATE,DWORD);
类中:
class TUDialNetwork{
public:
fp testfp;
}
调用中:
void __fastcall TUDialNetwork::beginDial()
{
testfp=&RasDialFunc;
int ret=RasDialA(NULL,NULL,¶ms,0,&testfp,&hrasconn);
}

pbMaster 2003-08-25
  • 打赏
  • 举报
回复
--keiy():
我刚才已经说过用static的问题了:如果把RasDialFunc申明为static,那在其内部就无法调用class TUDialNetwork的其他的非static成员了!
===
比如
if (OnDialError)
OnDialError( this,dwError,String(szRasString) );
--OnDialError是我在class中申明的一个事件。
zjqyb 2003-08-25
  • 打赏
  • 举报
回复
try 一下

typedef void WINAPI __fastcall(__closure *fp)(UINT,RASCONNSTATE,DWORD)
TUDialNetwork DialNetwork;

void test(UINT MSG,RASCONNSTATE rasconnstate,DWORD dwError)
{
fp fp1= &DialNetwork.RasDialFunc;
fp1(MSG,rasconnstate,dwError);
}
柯本 2003-08-25
  • 打赏
  • 举报
回复
用static
class TUDialNetwork{
public:
void __fastcall beginDial();
static void WINAPI RasDialFunc(UINT MSG,RASCONNSTATE rasconnstate,DWORD dwError);
} ;
void __fastcall TUDialNetwork::beginDial()
{
RASDIALPARAMS params;
HRASCONN hrasconn;
int ret=RasDial(NULL,NULL,¶ms,0,&RasDialFunc,&hrasconn);
}
pbMaster 2003-08-25
  • 打赏
  • 举报
回复
--zjqyb():
那只能在void WINAPI RasDialFunc中发向应用程序发消息了?
还有没有其他变通的解决办法?
zjqyb 2003-08-25
  • 打赏
  • 举报
回复
设置为dll中的callback函数,几乎没有办法
只能用static 方式
把TUDialNetwork中的其他被callback函数访问的成员也申明为static
pbMaster 2003-08-25
  • 打赏
  • 举报
回复
--zjqyb():
那有办法解决我的问题没有?
zjqyb 2003-08-25
  • 打赏
  • 举报
回复
void WINAPI TUDailNetwork::RasDialFunc 它是一个closure指针,不能转换成void *指针
加载更多回复(2)

1,221

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧