Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++ C MFC
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:
<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 4-Aug-11 22:01pm
Comments
SAKryukov at 5-Aug-11 4:07am
   
Tricky problem! My 5 for the question.
--SA
SanjeevSingh at 5-Aug-11 4:14am
   
mine 5 too
sanjeev
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 4

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.
  Permalink  
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 5

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.
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
  Permalink  
v2
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

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. Smile | :) )
 
—SA
  Permalink  
v4
Comments
Mizan Rahman at 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?
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

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.
  Permalink  
v3
Comments
Mizan Rahman at 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 at 5-Aug-11 8:34am
   
Number the functions and pass this number.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 6

Probably you should mimic (at least a subset of ) COM IDispatch functionality. The simplest solution I can imagine is
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.
  Permalink  
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 7

"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.
  Permalink  
Comments
Mizan Rahman at 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?

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

  Print Answers RSS
0 OriginalGriff 530
1 Sergey Alexandrovich Kryukov 330
2 BillWoodruff 299
3 PIEBALDconsult 230
4 CPallini 220
0 Sergey Alexandrovich Kryukov 10,615
1 Maciej Los 5,354
2 OriginalGriff 5,254
3 CPallini 3,719
4 BillWoodruff 3,476


Advertise | Privacy | Mobile
Web02 | 2.8.141029.1 | Last Updated 5 Aug 2011
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100