返回值为空的函数指针如何定义

tendollor 2010-02-20 05:31:29

int (__stdcall *gethostname1)(char *,int );
我用这样的方式定义函数指针 如果函数返回值为空的函数如何定义?

void (__stdcall *freeaddrinfo1)(struct addrinfo *); 我这样定义 编译报错

我要保存ws2_32.dll中的函数的调用地址 我想知道怎么定义指针保存这个地址

所以不要告诉我用可以其他的方法直接访问DLL中的函数




//之前这种定义
int (__stdcall *gethostname1)(char *,int );
//这种使用
proc=GetProcAddress(hModule,"gethostname");
gethostname1=(int (__stdcall *)(char *,int ))proc;


都没问题


换成void的就不行

光定义这句void (__stdcall *freeaddrinfo1)(struct addrinfo *);就出错
改成这样typedef void (__stdcall *freeaddrinfo1)(struct addrinfo *);才不出错

proc的定义
FARPROC proc; //函数指针入口

为了抛开proc类型的影响

改成这样写
freeaddrinfo1=( void (__stdcall *)(struct addrinfo *))GetProcAddress(hModule,"freeaddrinfo");


还是出错
E:\VC_WORK\GUA\sockfilter\winsock32.cpp(127) : error C2513: 'void (__stdcall *)(struct addrinfo *)' : no variable declared before '='



不知道要怎么写了
...全文
1554 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
stonexing5 2011-03-26
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 tendollor 的回复:]
貌似是的 没问题了
这个只是函数再导出表中申明 但是没实现的错误

OK了 谢谢了 我知道怎么回事了
还是有未定义的类型付

我真的要换VS08了
[/Quote]
楼上 大神语法没问题了
程序有问题么?
tendollor 2010-02-21
  • 打赏
  • 举报
回复
貌似是的 没问题了
这个只是函数再导出表中申明 但是没实现的错误

OK了 谢谢了 我知道怎么回事了
还是有未定义的类型付

我真的要换VS08了
tendollor 2010-02-21
  • 打赏
  • 举报
回复
加上之后
winsock32.def : error LNK2001: unresolved external symbol freeaddrinfo
winsock32.def : error LNK2001: unresolved external symbol getaddrinfo
Debug/sockfilter.lib : fatal error LNK1120: 2 unresolved externals
LINK : fatal error LNK1141: failure during build of exports file

抱着个错
lu_zi 2010-02-21
  • 打赏
  • 举报
回复
int main(){return 0;}
tendollor 2010-02-21
  • 打赏
  • 举报
回复
.H文件中
int (__stdcall *gethostname1)(char *,int );
CPP文件中
//其他未修改函数
proc=GetProcAddress(hModule,"gethostname");
gethostname1=(int (__stdcall *)(char *,int ))proc;

此写法正确 不报错
oathevil 2010-02-21
  • 打赏
  • 举报
回复
struct addrinfo
{
//
};

void (__stdcall *freeaddrinfo1)(struct addrinfo *);

你addrinfo这个结构体没定义吧? 像这样加上试试
tendollor 2010-02-21
  • 打赏
  • 举报
回复
我在CPP文件中仿照返回值不为空的函数的写法 写出了如下代码

//其他未修改函数
proc=GetProcAddress(hModule,"freeaddrinfo");
freeaddrinfo1=(void (__stdcall *)(struct addrinfo *))proc;


报错

e:\vc_work\gua\sockfilter\winsock32.cpp(137) : error C2440: '=' : cannot convert from '<Unknown>' to '<Unknown>'
This conversion requires a reinterpret_cast, a C-style cast or function-style cast
tendollor 2010-02-21
  • 打赏
  • 举报
回复
我在.H文件中这样定义时
void (__stdcall *freeaddrinfo1)(struct addrinfo *);

CPP文件什么都不写 就提示错误
E:\VC_WORK\GUA\sockfilter\winsock32.cpp(402) : fatal error C1001: INTERNAL COMPILER ERROR
(compiler file 'msc1.cpp', line 1786)
Please choose the Technical Support command on the Visual C++
Help menu, or open the Technical Support help file for more information
tendollor 2010-02-21
  • 打赏
  • 举报
回复
引用 8 楼 oathevil 的回复:
int  (__stdcall *gethostname1)(char *,int );
这是声明一个函数指针gethostname1
而函数指针的所指针的函数是一个参数类型依次是char *,int  且返回值为int的函数

在返回值为空的情况下, 当然会提示错误啦.


我指的是返回值为空的情况下 我定义当然就void (__stdcall *gethostname1)(char *,int );
这样定义了
oathevil 2010-02-21
  • 打赏
  • 举报
回复
int (__stdcall *gethostname1)(char *,int );
这是声明一个函数指针gethostname1
而函数指针的所指针的函数是一个参数类型依次是char *,int 且返回值为int的函数

在返回值为空的情况下, 当然会提示错误啦.
tendollor 2010-02-20
  • 打赏
  • 举报
回复
引用 5 楼 oathevil 的回复:
你是对函数指针的问题没搞清楚.
举个例子:

typedef (*test)(int,int);

test a,b;

等价于:

void (*a)(int,int);
void (*b)(int,int);

这里的两个a和b已经是一个实际的函数指针, 它指向的是以两个整型数据为参数,不返回值的指针.  而typedef (*test)(int,int);定义的是一个类型的函数指针,它可以实例化.  就像test a,b;  a、b是两个属于一种类型的函数指针

你代码中的
freeaddrinfo1=( void (__stdcall *)(struct addrinfo *))proc;
相当于强制类型转化,不能这样用.
freeaddrinfo1=(类型)proc;

比如说你可以像这样,  freeaddrinfo1=(test)proc;  将其强制转换成test这种类型的指针,这样就可以了.

再不清楚, 去看看typedef关于函数指针的用法
谢谢 这个看了你的说明之后 我已经清楚了



那现在int (__stdcall *gethostname1)(char *,int );
这种声明方式应该怎么理解?
为什么在返回值为void 的情况下 语法就不支持了呢?
oathevil 2010-02-20
  • 打赏
  • 举报
回复
补充个测试的小例子
#include "iostream.h"

void xxx(int,int);

typedef void (*test)(int,int);

test t1;

void (*a)(int,int);

int main()
{
a=xxx;
a(1,1);

t1=xxx;
t1(2,2);

return 0;
}

void xxx(int a,int b)
{
cout<<"a+b="<<a+b<<endl;
}
oathevil 2010-02-20
  • 打赏
  • 举报
回复
你是对函数指针的问题没搞清楚.
举个例子:

typedef (*test)(int,int);

test a,b;

等价于:

void (*a)(int,int);
void (*b)(int,int);

这里的两个a和b已经是一个实际的函数指针, 它指向的是以两个整型数据为参数,不返回值的指针. 而typedef (*test)(int,int);定义的是一个类型的函数指针,它可以实例化. 就像test a,b; a、b是两个属于一种类型的函数指针

你代码中的
freeaddrinfo1=( void (__stdcall *)(struct addrinfo *))proc;
相当于强制类型转化,不能这样用.
freeaddrinfo1=(类型)proc;

比如说你可以像这样, freeaddrinfo1=(test)proc; 将其强制转换成test这种类型的指针,这样就可以了.

再不清楚, 去看看typedef关于函数指针的用法
jixingzhong 2010-02-20
  • 打赏
  • 举报
回复
void (__stdcall *freeaddrinfo1)(struct addrinfo *);

应该没问题

typedef void (__stdcall *FUN)(struct addrinfo *);
然后再FUN freeaddrinfo1;
这样可以不?
白云飘飘飘 2010-02-20
  • 打赏
  • 举报
回复
typedef void (__stdcall *freeaddrinfo1)(struct addrinfo *);
freeaddrinfo addrinfo;
addrinfo=( freeaddrinfo1)GetProcAddress(hModule,"freeaddrinfo");
tendollor 2010-02-20
  • 打赏
  • 举报
回复
补上完整代码

//xxx.h文件
//相关变量申明
HMODULE hModule = NULL; //模块句柄
char buffer[1000]; //缓冲区
FARPROC proc; //函数指针入口

//定义指向原WinSock函数库地址的指针变量
SOCKET (__stdcall *socket1)(int ,int,int); //创建Sock函数
int (__stdcall *WSAStartup1)(WORD,LPWSADATA); //初始化WinSock库函数
int (__stdcall *WSACleanup1)(); //清除WinSock库函数
int (__stdcall *recv1)(SOCKET,char FAR *,int,int); //接收数据函数
int (__stdcall *send1)(SOCKET,const char *,int,int); //发送数据函数
int (__stdcall *connect1)(SOCKET,const struct sockaddr *,int); //创建连接函数
int (__stdcall *bind1)(SOCKET,const struct sockaddr *,int); //绑定函数
//…………
//…………
//在后面继续添加其他winsock32库函数中需要自定义的函数地址的指针变量
int (__stdcall *setsockopt1)(SOCKET,int,int,const char *,int); //sets a socket option
int (__stdcall *getsockopt1)(SOCKET,int,int,char *,int *); //Gets a socket option
int (__stdcall *WSARecvFrom1)(SOCKET,LPWSABUF,DWORD,LPDWORD,LPDWORD,struct sockaddr *,LPINT,LPWSAOVERLAPPED,LPWSAOVERLAPPED_COMPLETION_ROUTINE); //receives a datagram and stores the source address.
int (__stdcall *WSARecv1)(SOCKET,LPWSABUF,DWORD,LPDWORD,LPDWORD,LPWSAOVERLAPPED,LPWSAOVERLAPPED_COMPLETION_ROUTINE);
SOCKET (__stdcall *accept1)(SOCKET,struct sockaddr *,int *);
int (__stdcall *closesocket1)(SOCKET);
int (__stdcall *getpeername1)(SOCKET,struct sockaddr *,int *);
int (__stdcall *getsockname1)(SOCKET,struct sockaddr *,int *);
u_long (__stdcall *htonl1)(u_long);
u_short (__stdcall *htons1)(u_short);
int (__stdcall *ioctlsocket1)(SOCKET,long,u_long *);
unsigned long (__stdcall *inet_addr1)(const char *);
char* (__stdcall *inet_ntoa1)(struct in_addr );
int (__stdcall *listen1)(SOCKET,int );
u_long (__stdcall *ntohl1)(u_long );
u_short (__stdcall *ntohs1)(u_short );
int (__stdcall *recvfrom1)(SOCKET,char *,int,int,struct sockaddr *,int * );
int (__stdcall *select1)(int ,fd_set *,fd_set *,fd_set *,const struct timeval *);
int (__stdcall *sendto1)(SOCKET,const char *,int,int,const struct sockaddr *,int);
int (__stdcall *shutdown1)(SOCKET,int);
BOOL (__stdcall *WSApSetPostRoutine1)(PVOID); //没有MSDN资料的函数
//void (__stdcall *FreeAddrInfoW1)(PADDRINFOW);
struct hostent* (__stdcall *gethostbyname1)(const char *);
HANDLE (__stdcall *WSAAsyncGetHostByName1)(HWND ,u_int ,const char *,char *,int);//没有MSDN资料的函数
int (__stdcall *WSACancelAsyncRequest1)(HANDLE);
int (__stdcall *gethostname1)(char *,int );
typedef void (__stdcall *freeaddrinfo1)(struct addrinfo *);


//XXX.CPP文件
#include <stdio.h>

#include <winsock2.h>
#include <windows.h>
//#include <ws2tcpip.h>
//#include <wspiapi.h>
#include "winsock32.h"


//DLLMain函数入口
BOOL WINAPI DLLMain (HANDLE hInst,ULONG ul_reason_for_call,LPVOID lpReserved)
{
if(hModule==NULL)
{
//加载原来的WinSock库,原来的WinSock库被复制成wsock32.001
hModule=LoadLibrary("wsock32.001");
}
else return 1;
//获取原来WinSock库中所有的函数的地址并保存起来
if(hModule!=NULL)
{
//获取原来WinSock库初始化函数的地址,保存到WSAStartup1中
proc=GetProcAddress(hModule,"WSAStartup");
WSAStartup1=(int (__stdcall *)(WORD,LPWSADATA))proc;
//获取原来WinSock库清除函数的地址,保存到WSACleanup1中
proc=GetProcAddress(hModule,"WSACleanup");
WSACleanup1=(int (_stdcall *)())proc;
//接收数据函数
proc=GetProcAddress(hModule,"recv");
recv1=(int (__stdcall *)(SOCKET,char FAR *,int,int))proc;
//发送数据函数
proc=GetProcAddress(hModule,"send");
send1=(int (__stdcall *)(SOCKET,const char *,int,int))proc;
//创建连接函数
proc=GetProcAddress(hModule,"connect");
connect1=(int (__stdcall *)(SOCKET,const struct sockaddr *,int))proc;
//绑定函数
proc=GetProcAddress(hModule,"bind");
bind1=(int (__stdcall *)(SOCKET,const struct sockaddr *,int))proc;
//…………
//…………
//在后面继续把原来WinSock库中所有的函数的地址保存起来
proc=GetProcAddress(hModule,"setsockopt");
setsockopt1=(int (__stdcall *)(SOCKET,int,int,const char *,int))proc;


//中间N个函数代码略

//其他未修改函数
proc=GetProcAddress(hModule,"gethostname");
gethostname1=(int (__stdcall *)(char *,int ))proc;
//其他未修改函数
// proc=GetProcAddress(hModule,"freeaddrinfo");
// freeaddrinfo1=( void (__stdcall *)(struct addrinfo *))proc;
freeaddrinfo1=( void (__stdcall *)(struct addrinfo *))GetProcAddress(hModule,"freeaddrinfo");

}
else return 0;
return 1;
}




//定义库输出函数

//WinSock初始化函数定义
int PASCAL FAR WSAStartup(WORD wWersionRequested,LPWSADATA lpWSAData)
{
//调用原来的WinSock初始化函数
return WSAStartup1(wWersionRequested,lpWSAData);
}





//WinSock清除函数
int PASCAL FAR WSACleanup()
{
//调用原来的WinSock清除函数
return WSACleanup1();
}




//创建Socket函数
SOCKET PASCAL FAR socket(int af,int type,int protocol)
{
//调用原来的创建Socket函数
return socket1(af,type,protocol);
}

//中间N个函数定义略

int PASCAL FAR gethostname(char *name,int namelen)
{
return gethostname1(name,namelen);
}



//DEF文件
LIBRARY "sockfilter"
EXPORTS
;WSAStartup @1
;WSACleanup @2
;recv @3
;send @4
;socket @5
;bind @6
;closesocket @7
;connect @8

;其他输出函数列表
;…………
;…………


accept @1
bind @2
closesocket @3
connect @4
getpeername @5
getsockname @6
getsockopt @7
htonl @8
htons @9
ioctlsocket @10
inet_addr @11
inet_ntoa @12
listen @13
ntohl @14
ntohs @15
recv @16
recvfrom @17
select @18
send @19
sendto @20
setsockopt @21
shutdown @22
socket @23
WSApSetPostRoutine @24
;FreeAddrInfoW @25
;GetAddrInfoW @26
;GetNameInfoW @27
;WPUCompleteOverlappedRequest @28
;WSAAccept @29
;WSAAddressToStringA @30
;WSAAddressToStringW @31
;WSACloseEvent @32
;WSAConnect @33
;WSACreateEvent @34
;WSADuplicateSocketA @35
;WSADuplicateSocketW @36
;WSAEnumNameSpaceProvidersA @37
;WSAEnumNameSpaceProvidersW @38
;WSAEnumNetworkEvents @39
;WSAEnumProtocolsA @40
;WSAEnumProtocolsW @41
;WSAEventSelect @42
;WSAGetOverlappedResult @43
;WSAGetQOSByName @44
;WSAGetServiceClassInfoA @45
;WSAGetServiceClassInfoW WSAGetServiceClassInfoW @46
;WSAGetServiceClassNameByClassIdA @47
;WSAGetServiceClassNameByClassIdW @48
;WSAHtonl @49
;WSAHtons @50
;gethostbyaddr @51
gethostbyname @52
;getprotobyname @53
;getprotobynumber @54
;getservbyname @55
;getservbyport @56
gethostname @57
;WSAInstallServiceClassA @58
;WSAInstallServiceClassW @59
;WSAIoctl @60
;WSAJoinLeaf @61
;WSALookupServiceBeginA @62
;WSALookupServiceBeginW @63
;WSALookupServiceEnd @64
;WSALookupServiceNextA @65
;WSALookupServiceNextW @66
;WSANSPIoctl @67
;WSANtohl @68
;WSANtohs @69
;WSAProviderConfigChange @70
WSARecv @71
;WSARecvDisconnect @72
WSARecvFrom @73
;WSARemoveServiceClass @74
;WSAResetEvent @75
;WSASend @76
;WSASendDisconnect @77
;WSASendTo @78
;WSASetEvent WSASetEvent @79
;WSASetServiceA @80
;WSASetServiceW @81
;WSASocketA WSASocketA @82
;WSASocketW WSASocketW @83
;WSAStringToAddressA @84
;WSAStringToAddressW @85
;WSAWaitForMultipleEvents @86
;WSCDeinstallProvider @87
;WSCEnableNSProvider @88
;WSCEnumProtocols @89
;WSCGetProviderPath @90
;WSCInstallNameSpace @91
;WSCInstallProvider @92
;WSCUnInstallNameSpace @93
;WSCUpdateProvider @94
;WSCWriteNameSpaceOrder @95
;WSCWriteProviderOrder @96
; freeaddrinfo @97
;getaddrinfo @98
;getnameinfo @99
;Noname100 Noname100 @100 NONAME
;WSAAsyncSelect @101
;WSAAsyncGetHostByAddr @102
WSAAsyncGetHostByName @103
;WSAAsyncGetProtoByNumber @104
;WSAAsyncGetProtoByName @105
;WSAAsyncGetServByPort @106
;WSAAsyncGetServByName @107
WSACancelAsyncRequest @108
;WSASetBlockingHook @109
;WSAUnhookBlockingHook @110
;WSAGetLastError @111
;WSASetLastError @112
;WSACancelBlockingCall @113
;WSAIsBlocking @114
WSAStartup @115
WSACleanup @116
M_S_D_N 2010-02-20
  • 打赏
  • 举报
回复
你的完整代碼寫成咋樣都沒發出來。。。

64,691

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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