Advertisement

Advance Function Calling....

Started by March 06, 2000 08:17 PM
6 comments, last by Mike 24 years, 7 months ago
I think I just created another useless topic that the AP Computer Science people could put in their curriculum. Anyway, I have a question about calling functions. I need to write a function that can call any other function. The other function needs to be able to have any kind of parameter list. Here is an example; the "calling" function needs to be able to call both of the functions below: void PrintTheText( char* text ) void AddTheNumbers( int a, int b, int &total ); The reason for this is that I am writing a scripting language that can call native C++ functions. I need to write a function that the virtual machine can use to call native functions. I've come up with a way to accomplish this but it is not pretty. I would appreciate it if some of you better programmers out there would download the source code and take a look at it. I'm hopping there is a better way to do accomplish the task. Edited by - Mike on 3/6/00 8:20:34 PM
I''ve been trying to figure out a similar problem - but instead of a function that takes a variety of parameters I want to create a generic function pointer ( a pointer that will point to any function without casts, etc..) since the problems are similar - If anyone has any ideas I''d also like to hear them...
Advertisement
Hmmm.. Interesting,

try something like this:
typedef (void *) (* Fxn)(void *);

That should allow any function Fxn to return any one argument and take in any one argument.
An alteration to this would be that if you know that you never need to pass more than 3 params, you could have it declared like this:
typedef (void *) (* Fxn)(void *, void *, void *);

The functions you have would become:
void PrintTheText (void * text, void * not_used1 = NULL, void * not_used2 = NULL);
void AddTheNumbers (void * a, void * b, void * total);

When you call PrintTheText, you would do so, like this:
PrintTheText (text);
since not_usedx are automatically passed as NULL.

Alternately you could do this:

typedef (void *) (*Fxn)(...);
This is printf-like (Yes, you actually put ''...'' in the parens) and you must extract the variables using varlists (look at any C reference or under MSDN if you have it). Though I find that this is usually a pain.

Anyway, It is after 1AM and I am no longer lucid... so please take my advice with a grain (or two!) of salt.

-OberonZ

---
PAGE FAULT: Please insert "Swap File, Disk 2"
and press any key to continue.
---
PAGE FAULT: Please insert "Swap File, Disk 2"
and press any key to continue.
I''ve already posted to both your threads how to use C to call generic function pointers.

But if you''re using C++, why not just pass objects instead of functions? ex: Create a class, with a pure virtual Call() method, and inherit classes from that class, overriding the Call method. Then in each of those objects put the parameters in the object and invoke the virtual Call() method. That will allow your function calling function to call an method with any given set of parameters.
I''ll try to explain the problem a differnet way. Lets say you''re writing a program and you want to include a scripting language but you don''t know how to write your own. For this reason you include the scripting language that I''ve written. Then you just create an instance of the CCompiler class and the CVirtualMachine class.

Now, you want the scripting langauge to be able to call your functions. So what you would do is this:

void AddNumbers( int a, int b, int c ){        //some code}void main(){        CCompiler compiler;        CVirtualMachine vm;        CScript script;        compiler.ExportFunction( "AddNumbers", AddNumbers, param_count );        compiler.Compile( "demo.s", &script );        vm.RunScript( &script );} 


Doing this will allow any scripts compiled to call the exported function. Do you see what I''m trying to do? I do not know what functions the scripts are going to call. And cllearly I am using C++.
Your idea is brilliant! You just need to make it work... Do you mind if I borrow it and add the ExportFunction thing to my scripting languange? I think I know how to make it work.

look at this super-stripped-down-and-will-not-work-without-implementation code (forgive my non-hungarian notation):

class Variable
{
public:
char *Value;
int Size;
int GetIntValue() {return atoi(Value);}
char *GetCharValue() {return Value;}
Variable(int);
void SetValue(char *); // figure this one out later...
}

Variable::Variable(int TempSize)
{
Size = TempSize;
Value = new char[Size];
}

class Command
{
public:
virtual Command *Execute(); // override with each command
// returns pointer to next command in the linked list of commands
Variable *Params;
int NumParams;
Command(int);
void SetParam(int i, char *Value) {Params->SetValue(Value);}<br>}<br><br>Command::Command(int TempParams)<br>{<br>NumParams = TempParams;<br>Params = new Variable[NumParams];<br>}<br><br>Get the idea? If you make the execute function read the params specially, you can make the command take any number of parameters, and you can have the execute function pass those parameters to another function that it has a pointer to. With a little bit of work, you can have a user creating their own commands! Hope this helps… BTW: this code is right out of my scripting language (with some little things removed, obviously). I propose to trade this idea for your idea of letting the user add commands <img src="smile.gif" width=15 height=15 align=middle> <br><br>——————–<BR><BR><br>You are not a real programmer until you end all your sentences with semicolons;<BR><A HREF="http://www.trak.to/rdp" TARGET=_blank>www.trak.to/rdp</A> <P> <A HREF="mailto:Yanroy@usa.com">Yanroy@usa.com</A> <P><br><br>Edited by - Yanroy on 3/7/00 9:50:00 AM
--------------------

You are not a real programmer until you end all your sentences with semicolons; (c) 2000 ROAD Programming
You are unique. Just like everybody else.
"Mechanical engineers design weapons; civil engineers design targets."
"Sensitivity is adjustable, so you can set it to detect elephants and other small creatures." -- Product Description for a vibration sensor

Yanroy@usa.com

Advertisement
Here''s a tip.

If in your script you know what parameters are to be called, you could manually push to the stack.
PS: You must be aware of the type of calling conversion the programmer is using. _stdcall has nothing in common to the C standard conversion method.

c ''ya
... LEMMINGS ... LEMMINGS ... LEMMINGS ... LEM..... SpLaSh!...Could this be what we stand like before the mighty One?Are we LeMmIngS or WhAt!? ;)
Try this:


typedef char byte;
enum DataT
{
tChar,
tCharPtr,
tInt32,
tInt32Ptr,
tFloat32,
tFloat32Ptr,
tFloat64,
tFloat64Ptr,
};
struct DataHolder
{
byte Data[8];
DataT DataType;
};
typedef DataHolder * GenericFuncPtr(...);
static DataHolder g_Data;
// some sample functions to demonstrate
// AddTwoNumbers
DataHolder * AddTwoNumbers(void * start, ...)
{
va_list Params;
va_start(Params, start);
DataHolder DH;
DH.DataType = tInt32;
int32 * IntPtr = (int32*)DH.Data;
int32 a, b;
a = va_arg(Params, int32);
b = va_arg(Params, int32);
*IntPtr = a + b;
va_end(Params);
g_Data = DH;
return &g_Data;
}
DataHolder * AddThreeNumbers(void * start, ...)
{
va_list Params;
va_start(Params, start);
GenericFuncPtr * FP = (GenericFuncPtr*)AddTwoNumbers;
DataHolder DH = *FP(NULL, va_arg(Params, int32), va_arg(Params, int32));
DH = *FP(NULL, *(int32*)(DH.Data), va_arg(Params, int32));
va_end(Params);
g_Data = DH;
return &g_Data;
}



I just wrote and tested that code, and as far as I tested it works just fine. All the function pointers and ellipsis argument lists are a bit confusing, but not much more than using plain old void pointers initialized to NULL. Plus you can have an unlimited number of arguments. Feel free to change the (void*) parameter to anything you like, as it is just there as a reference to get the list of next arguments. You might even find some way to make the parameter useful, say make it latent or whatever.

When exporting your function pointers, just be sure that you don''t use the wrong parameters on an exported function. Maybe you can use an array of DataType elements and an int to specify the number and types of arguments when you export the function.

Have fun. Let me know if you need me to explain further or write some better code.

Andy Campbell
ICQ: 6708811
e-mail: bobandy@hotmail.com

This topic is closed to new replies.

Advertisement