Click here to Skip to main content
15,885,870 members
Please Sign up or sign in to vote.
5.00/5 (4 votes)
See more:
hi,

I have a function that receive a function pointer and an XML string which has the defination of the function and the argument per say:

void CallFunction( void * pFuncion, std::string xmlFuncionDef)
{

}

Inside the above function, xmlFunctionDef contains the defination of the function pointed by pFunction. For example, number paramter, type of each parameter, and the arguments:
XML
<Function ParamCount="3" ReturnType="int">
  <Params>
    <Param type="int" DefaultValue="None" PassBy="Value"/>
    <Param type="double" DefaultValue="None" PassBy="Referenc"/>
    <Param type="char*" DefaultValue="None" PassBy="Pointer"/>
  </Params>

  <Arguments>
   <Arg Value="3" />
   <Arg Value="29.5" />
   <Arg Value="Hello World" />
  </Arguments>
</Function>


Now how can I call this function? Should I use _asm for this? Any help would be highly appriciative.

/Mizan
Posted
Comments
Sergey Alexandrovich Kryukov 5-Aug-11 4:07am    
Tricky problem! My 5 for the question.
--SA
[no name] 5-Aug-11 4:14am    
mine 5 too
sanjeev

First you need the function prototype:
typedef std::string (*xmlFuncionDef)(void*);

Then your function looks alike:
void CallFunction( void * pFuncion,xmlFuncionDef fn)
{
 //...
}

Then you can call the function as follows:
void CallFunction( void * pFuncion,xmlFuncionDef fn)
{
  std::string result = (*fn)(pFuncion);
  // ...
}

The call of your function:
std::string MyxmlFuncionDef(void* p)
{
  std::string r;
  // get the result
  return r;
}
void main()
{
  void* p = 0;
  // initialize the data pointer 'p'
  CallFunction(p,&MyxmlFuncionDef);
}

Good luck.
 
Share this answer
 
Hi Mizan Rahman,
I remembered one of my friend is working exactly on the same problem.That time we used asm code to call functions with vc compiler.Though it is working fine for vc, it is not portable.After searching we found a library called libffi.This worked well for us.Take a look into that library.download the library,check the examples in .\testsuite\libffi.call folder.

BTW,the following is asm code we tried.
C#
int fun(int a, int b, int c)
{
    int x;
    x = a + b + c;
    return 0;
}
int main()
{
    int x = 9;
    int y = 10;
    int z = 11;
    _asm
    {
        mov         eax,dword ptr [z]
        push        eax
        mov         eax,dword ptr [y]
        push        eax
        mov         eax,dword ptr [x]
        push        eax
        call        fun     //call fun(x,y,z);
        add         esp,12 //12 size of total arguments in byte
    }
    return 0;
}


If you have any doubts give reply.

-venkatanarayana
 
Share this answer
 
v2
In ANSI C, it is not legal to cast between a function pointer and a data pointer.

A function pointer conveys the whole function signature with it, so passing the function pointer as a void* is just hopeless, the compiler won't be able to reconstruct an appropriate stack frame.

You'd better pass a function index (your program defines a fixed number of relevant functions) and write explicit calls, passing the corresponding parsed argument values.
 
Share this answer
 
v3
Comments
Mizan Rahman 5-Aug-11 7:14am    
I just tested your statement, and you are right. then what should it be (if not void *)? what can I use to store a pointer to any function?
YvesDaoust 5-Aug-11 8:34am    
Number the functions and pass this number.
Probably you should mimic (at least a subset of ) COM IDispatch functionality. The simplest solution I can imagine is
C++
void CallFunction( void (* pFun)(Par p[], int count), std::string xmlParDef)
{
  // parse xml parameters, build the p array
   
  // call the pFun function passing p
}


where Par is a union similar to the VARIANT one.
 
Share this answer
 
"Should I use _asm for this? "

yes, you can see the c & asm mixed programming, following the below steps:
1. parse xml and get a parameters array (c++)
2. push the parameters (asm, c language order)
3. call the function address (asm)
4. get the return value (asm)

The asm code is based on OS environment.
 
Share this answer
 
Comments
Mizan Rahman 9-Aug-11 6:40am    
Hi, I'm having problem writing __asm code block. I created a MFC dialog based app on my Windows7 64bit OS in VS2008. In my OnOK override, I pasted the code from 'http://msdn.microsoft.com/en-us/library/y8b57x4b(v=VS.90).aspx'. But I get error:
Error1 error C2415: improper operand type

Any idea why?
Just few notes. I feel the solution of this problem is possible, but it's very hard or maybe not possible to do it in a portable way. If you use inline Assembly, it will be quite complex Assembly code, even in the case of inline Assembly where you can call any helper functions written in C++ from within Assembly code.

At this moment, I cannot imagine how it can be possible to do without Assembly, but using Assembly language will make a solution non-portable.

It hardly can be solved in few minutes or hours; in my estimate, it could take days.

This is what in terms if .NET is called System.Reflection.Emit.

First of all, you need to know XML schema in full, and the interpretation of all of the keywords: all allowed types and parameter passing methods. You also need to know calling model (C, stdcall, etc.).

You will need some internal hash table which identify each type keyword and find the reference to some class/stucture which hold the description of each type: it's size and the method of the creation of the instance of this type by its value found in XML.

The code should get all parameters one by one, find the type property, create and initialize the instance (creating references/pointers as required by the parameter passing type) and put them on stack. Where you emit a call depends on calling model. Most likely, you will need separate implementations, at list the implementation for C calling model should be separate from others.

(For a record: I really doubt this architecture of RPC (in a way, what you describe can be considered as a kind of Remote Procedure Call) is good. It's hard to implements and can incur heavy reliability and portability problems. I think even the bloated and limited SOAP-based model is better. (I would say the good one is WCF.)

However, I can imagine this is something like a stroke of a genius which I simply did not understand. :-))

—SA
 
Share this answer
 
v4
Comments
Mizan Rahman 5-Aug-11 4:37am    
For the sake of simplicity, let say the call would be stdcall, all parameters would be double and all parameters are passed by value. And say I already have a parser that can read the xml string and can create an array of double for arguments.
GetArguments(std::string xml, double *& pDbl, int & count);

So now only variable is the number of parameters. How would go about doing that?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900