LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-02-2008, 03:52 PM   #1
R00ts
Member
 
Registered: Mar 2004
Location: Austin TX, USA
Distribution: Ubuntu 11.10, Fedora 16
Posts: 547

Rep: Reputation: 30
Question C++: obtaining and printing a function signature


I need to write a wrapper around an API that prints out a message containing the name of the API function invoked, the list of arguments passed, and the return value of the call. I'm wondering if it would be possible to do this a little bit more intelligently than I am right now (I'm currently writing a wrapper function for each API function). Each wrapper function pretty much does the same thing (with a few special case exceptions):


1) Print the name of the API function being called and the values of each argument
2) Call the API function
3) Print the return value of the function
4) If the return value is now what we expected to receive, print an error message


So I can't help but feel there's a better way to do this. Maybe by providing a single generic function for doing the above steps for any API function called. Does anyone have any clever ideas about this? I've been thinking about possible approaches but haven't come up with any good leads. Also I'm trying to avoid unnecessary dependencies in this code (ie, no boost). I'm not sure if there's an answer for this or not, but thanks for any insight you can share with me.
 
Old 01-02-2008, 05:58 PM   #2
harry edwards
Member
 
Registered: Nov 2007
Location: Lincolnshire, UK
Distribution: CentOS, Fedora, and Suse
Posts: 365

Rep: Reputation: 48
I believe C++ doesn't cater for what you ask; however, certain compilers supply MACROs which maybe of use. GCC provides three magic variables which hold the name of the current function, as a string. These are:

__func__
__FUNCTION__
__PRETTY_FUNCTION__

others of interest standardized by ANSI C are:

__LINE__
__FILE__
__TIME__
__DATE__
 
Old 01-02-2008, 06:05 PM   #3
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
If you wrote the API then you could use variables in gcc such as __FUNCTION__ and __PRETTY_FUNCTION__ and on windows the __FUNCTION__ macro. If you did not write the API then I would say you would have to use macros to generate code for you as a proxy function or to generate a template function. The following is untested yet should work, yet it assumes that the parameters and results can be inserted to a stream and they are not member functions.

Code:
#include <iostream>

int test0()
{
 	 std::cout <<"called test0"<<std::endl;
 	 return 0;
}
int test1(int t)
{
 	 std::cout <<"called test1"<<std::endl;
 	 return 1;
}
int test2(int t,int t1)
{
 	 std::cout <<"called test2"<<std::endl;
 	 return 2;
}
int test3(int t,int t1,int t2)
{
 	 std::cout <<"called test3"<<std::endl;
 	 return 3;
}
int test4(int t,int t1,int t2,int t3)
{
 	 std::cout <<"called test4"<<std::endl;
 	 return 4;
}
#define PARAM0()
#define PARAM1(T1 ) T1 p1 
#define PARAM2(T1,T2) PARAM1(T2), T2 p2
#define PARAM3(T1,T2,T3) PARAM2(T1,T2), T3 p3
#define PARAM4(T1,T2,T3,T4) PARAM3(T1,T2,T3), T4 p4


#define PRINT_NAME(Name)std::cout <<#Name <<" "
#define PRINT_AND_RETURN\
		std::cout <<"result: "<<r <<std::endl;\
		if(r != expected)std::cout <<"Error expected " <<expected <<std::endl;\
		return r;
		
#define PRINT_PARAM1(p1_)\
		<<p1_ <<" " 
		
#define PRINT_PARAM2(p1_,p2_)\
		PRINT_PARAM1(p1_) <<p2_ <<" " 
		
#define PRINT_PARAM3(p1_,p2_,p3_)\
		PRINT_PARAM2(p1_,p2_) <<p3_ <<" " 
		
#define PRINT_PARAM4(p1_,p2_,p3_,p4_)\
		PRINT_PARAM3(p1_,p2_,p3_) <<p4_ <<" " 
						
#define PROXY_FUNCTION_0(Return,Name)\
namespace PROXY\
{\
	Return Name(Return expected)\
	{\
		PRINT_NAME(Name)<< std::endl;\
		Return r = ::Name();\
		PRINT_AND_RETURN\
	}\
}
#define PROXY_FUNCTION_1(Return,Name,P1)\
namespace PROXY\
{\
	Return Name( PARAM1(P1),Return expected )\
	{\
		PRINT_NAME(Name)\
		PRINT_PARAM1(p1)<< std::endl;\
		Return r =  ::Name( p1 );\
		PRINT_AND_RETURN\
	}\
}

#define PROXY_FUNCTION_2(Return,Name,P1,P2)\
namespace PROXY\
{\
	Return Name( PARAM2(P1,P2),Return expected )\
	{\
		PRINT_NAME(Name)\
		PRINT_PARAM2(p1,p2)<< std::endl;\
		Return r =  ::Name(p1,p2);\
		PRINT_AND_RETURN\
	}\
}

#define PROXY_FUNCTION_3(Return,Name,P1,P2,P3)\
namespace PROXY\
{\
	Return Name( PARAM3(P1,P2,P3),Return expected )\
	{\
		PRINT_NAME(Name)\
		PRINT_PARAM3(p1,p2,p3)<< std::endl;\
		Return r =  ::Name( p1,p2,p3);\
		PRINT_AND_RETURN\
	}\
}

#define PROXY_FUNCTION_4(Return,Name,P1,P2,P3,P4)\
namespace PROXY\
{\
	Return Name( PARAM4(P1,P2,P3,P4),Return expected )\
	{\
		PRINT_NAME(Name)\
		PRINT_PARAM4(p1,p2,p3,p4)<< std::endl;\
		Return r =  ::Name( p1,p2,p3,p4);\
		PRINT_AND_RETURN\
	}\
}

PROXY_FUNCTION_0(int,test0)
PROXY_FUNCTION_1(int,test1,int)
PROXY_FUNCTION_2(int,test2,int,int)
PROXY_FUNCTION_3(int,test3,int,int,int)
PROXY_FUNCTION_4(int,test4,int,int,int,int)

int main(int argc, char *argv[])
{
 	PROXY::test0(0);
 	PROXY::test1(1,1);
 	PROXY::test2(1,2,2);
 	PROXY::test3(1,2,3,3);
 	PROXY::test4(1,2,3,4,5);// should cause an error
    return 0;
}
 
Old 01-03-2008, 04:02 AM   #4
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
There are problems with the sample code I posted such as not being able to detect pointers to types instead of types, not using epsilon range checking for floating point types, can not use member functions etc etc these can all be solved but more information would be required such as but not limited to:
How is the api linked?
Is it a c or c++ api?
what types are the parameters?
Do you have a functor library, if not could you not use loki's(headers only)?
Because I am nosey which API is it?
 
Old 01-07-2008, 11:54 AM   #5
R00ts
Member
 
Registered: Mar 2004
Location: Austin TX, USA
Distribution: Ubuntu 11.10, Fedora 16
Posts: 547

Original Poster
Rep: Reputation: 30
Sorry I've been busy the past few days and haven't gotten around to reading this thread. Thanks for the responses.

Quote:
Originally Posted by dmail View Post
How is the api linked?
Is it a c or c++ api?
what types are the parameters?
Do you have a functor library, if not could you not use loki's(headers only)?
Because I am nosey which API is it?
- dynamically linked I believe
- C
- mostly integer types and pointers. No floating point
- I can't add any library dependencies

The API is device driver software for VXI controllers. The code I'm writing has to work for Windows, Linux, OS X, Solaris, VxWorks, Pharlap, and possibly other OSes. Of course, this means it also needs to work with various compilers. I've decided to go ahead and just do it the tedious manual way, as there are some specific scenarios where I want the wrapper function to do something atypical. Thanks for the help though
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
obtaining DNS from DHCP mohtasham1983 Linux - Networking 3 12-24-2005 07:44 PM
Help obtaining ip address colombo187 Linux - Wireless Networking 4 12-28-2004 05:29 PM
Obtaining an IP through DHCP orange400 Linux - General 1 06-09-2004 03:05 PM
A main can be changed by a function local without passing anything to the function? ananthbv Programming 10 05-04-2004 01:31 PM
Perl exec function in linux (and system-function) nazula Programming 1 04-19-2004 12:21 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:45 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration