.:: Bots United ::.

.:: Bots United ::. (http://forums.bots-united.com/index.php)
-   General Programming (http://forums.bots-united.com/forumdisplay.php?f=25)
-   -   Storing an array of function calls, and their params..... (http://forums.bots-united.com/showthread.php?t=3977)

Maleficus 16-05-2005 00:05

Storing an array of function calls, and their params.....
 
Lets say I have a struct that looks somewhat like in this example (note, this is just example code, its not put here as compilable/logical code):

Code:

typedef struct
{
        int                foo;
        int (*fooFunc) (int *param1, int *param2);
} my_func_t;

my_func_t *func_array[64];


Now, in a function in the code, I want to loop thru and fill that array with different functions and params, so that I can just call them by reference later.

i.e.

Code:

my_func_t *callerFunc;
int i = 0;
char *myChar;
while (i < 64)
{
        callerFunc = func_array[i];

        if ( i == 1)
          callerFunc->fooFunc = MyCoolFunc(12, 13);
 
  if (i == 2)
          callerFunc->fooFunc = MyCoolFunc(44, 22);


//  ETC, ETC, ETC......
 
  i++;
}

int MyCoolFunc( int parameter1, int parameter2) {

// CODE GOES HERE
}

Now, later I want to loop thru "func_array" and just call the function that was passed to it, and its parameters.

I haven't gotten as far as calling the function pointer again tho, I'm just in the part where I save the array of functions, and get this warning:

warning C4047: '=' : 'int (__cdecl *)(int ,int )' differs in levels of indirection from 'int '


I'm sure its something simple, but its bugging me. :o

Lazy 16-05-2005 00:15

Re: Storing an array of function calls, and their params.....
 
fooFunc is a function pointer and you are assigning it an integer which is what MyCoolFunc is returning.
The easiest way to do what you want is simply add iParam1, iParam2, ect... to your struct then just do something like array[ slot ].fooFunc( array[slot ].iParam1, array[ slot ].iParam2 );

Unless I missed the point...

Maleficus 16-05-2005 00:24

Re: Storing an array of function calls, and their params.....
 
Quote:

Originally Posted by Lazy
fooFunc is a function pointer and you are assigning it an integer which is what MyCoolFunc is returning.
The easiest way to do what you want is simply add iParam1, iParam2, ect... to your struct then just do something like array[ slot ].fooFunc( array[slot ].iParam1, array[ slot ].iParam2 );

Unless I missed the point...

No, no - thats exactly what I'm looking for, I'll try it later when I get some time.

What I don't understand is, I've had no problem in the past doing essentially the same thing, but instead of being passed 2 ints, its passed 1 sturct.


Thanks! :D

Pierre-Marie Baty 16-05-2005 15:03

Re: Storing an array of function calls, and their params.....
 
thinking in terms of memory occupation helps a lot. You have:
Code:

typedef struct
{
        int foo; // this is an integer, i.e. 4 bytes
 
        // this is a pointer, thus a long, i.e. 4 bytes too.
        int (*fooFunc) (int *param1, int *param2);
} my_func_t;

fooFunc is a pointer, which means, no matter how many trailing parameters you put on that line to the fooFunc function, its representation will be identical in every instance of the struct: 4 bytes, filled with the address of the function you will be calling.

With this:
Code:

callerFunc->fooFunc = MyCoolFunc(12, 13);

you are not storing the address of MyCoolFunc and its parameters, you are CALLING MyCoolFunc() with 12 and 13 as parameters, and storing... its return value.

That's not quite the same thing!

Lazy 16-05-2005 21:24

Re: Storing an array of function calls, and their params.....
 
Actually, there might be a way to do this.
What you need to do is create a function on the fly that would push the different numbers onto the stack then call MyCoolFunc then set the function pointer to the newly created function.
All you really need to do that is the 386 datasheet ( I think thats the one ) for the instruction info then go and build your function byte by byte.

Maleficus 16-05-2005 22:06

Re: Storing an array of function calls, and their params.....
 
I did a quick test last night, and it seemed to work just fine the way you described it Lazy.

I kept everything in the scruct the same, but I added two ints that hold the parameters, and instead of doing this:

Code:

callerFunc->fooFunc = MyCoolFunc(44, 22);
I do this:

Code:

callerFunc->fooFunc = MyCoolFunc;
Which compiles fine without errors. Then, when I want to exec the function that occupies that array spot, I do this:

Code:

callerFunc->fooFunc(callerFunc->param1, callerFunc->param2);
And at least for the quick test that I did, it ran perfectly, doing exactly what I wanted it to do.

Thanks again for the help!

@$3.1415rin 16-05-2005 22:07

Re: Storing an array of function calls, and their params.....
 
bye bye portability

Lazy 16-05-2005 22:08

Re: Storing an array of function calls, and their params.....
 
How is my suggestion not portable?
The dynamic function creation is so far windows specific but the function pointer stuff isn't.

I'll have an example soon, the call instruction is giving me problems just like jmp did when I was writing my API hooking class.

Maleficus 16-05-2005 22:11

Re: Storing an array of function calls, and their params.....
 
At the risk of getting flamed: I'm writing to windows, and TBH, I have no access to any other OS, so I'm not worried if its windows only.

As long as it works, I'm happy.

@$3.1415rin 16-05-2005 22:13

Re: Storing an array of function calls, and their params.....
 
well, I guess one shouldnt directly mess with the stack, at least not when coding 'normal' c/c++ code.

@mal : there is a crossed out A, mark your texts and click on it, so the color information is discarded.

why is such stuff needed btw ? wouldnt virtual functions and polymorphism do the trick ? never ran across such problems, therefore just asking

Lazy 16-05-2005 22:20

Re: Storing an array of function calls, and their params.....
 
Because, normal C++ is only fun when you do crazy things that either won't work or are a miracle when they do.

The crazy idea I had was to dynamically make a function that would call the other function with the appropriate parameters.

Like...
push ( b )
push ( a )
call ( MyCoolFunc )
pop ( eax )
pop ( eax )
ret

Then set that little function as your function pointer, though since I don't know that much about assembly it's a little harder for me to get this working. Almost done though.

@$3.1415rin 16-05-2005 22:23

Re: Storing an array of function calls, and their params.....
 
yep, I know such stuff ... jump to subroutines with the normal jump, to save a following 'return from subroutine' etc ... but normally I rather try to keep assembly and C/C++ separated. this had already positive effects when I had to ran a program on a non x86 machine at university :-)

Maleficus 16-05-2005 22:26

Re: Storing an array of function calls, and their params.....
 
I'm coding for a game thats written in straight C, so virtual functions aren't available to me (easily anyway).

I'm creating a script system that is event based. The user can tell the game a bunch of different commands to execute when a certain event happens.

What I was looking to do, is parse the file, then save off the commands that are linked to each event happening in a stack like the one we're talking about.

Then, when the event happens, I can quickly execute the commands linked to that event, without reparsing anything, or working with strings.

It seemed the quickest way to do what I needed to do. If theres a better way, I'd be happy to hear about it, I'm always open to learning more, especially if its faster, or more efficient.

Lazy 16-05-2005 22:29

Re: Storing an array of function calls, and their params.....
 
There is probably a way to make the compiler do all the work but I haven't found it yet.
Not fun writing a function byte by byte though, calls fine now, just won't pop the stuff off the stack lol.
*goes insane*

Lazy 16-05-2005 22:40

Re: Storing an array of function calls, and their params.....
 
WARNING: Disgusting, hacked up code!

Code:

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tlhelp32.h>
#include <conio.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include "remotemodule.h"

#define FUNCTION_SIZE 18
// Dynamically generated function
// ------
// push ( b )                5 bytes
// push ( a )                5 bytes
// call ( pfnAdd )  5 bytes
// pop ( eax )          1 byte
// pop ( eax )          1 byte
// ret                          1 byte

int Add( int iA, int iB ) {
  return printf( "%d\n", iA + iB );
}

typedef int ( __cdecl* tAdd ) ( int, int );

struct function_s {
  tAdd pfnAdd; // Adds two numbers
}
gFunctionlist[ 4 ];

BYTE* CreateAddFunction( int iA, int iB ) {
  BYTE* pMemory = NULL;

  // Use this instead of malloc so this area in memory can run code
  pMemory = ( BYTE* ) VirtualAlloc( NULL, FUNCTION_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE );

  if ( pMemory ) {
          pMemory[ 0 ] = 0x68;
          pMemory[ 1 ] = LOBYTE( LOWORD( iB ) );
          pMemory[ 2 ] = HIBYTE( LOWORD( iB ) );
          pMemory[ 3 ] = LOBYTE( HIWORD( iB ) );
          pMemory[ 4 ] = HIBYTE( HIWORD( iB ) );

          pMemory[ 5 ] = 0x68;
          pMemory[ 6 ] = LOBYTE( LOWORD( iA ) );
          pMemory[ 7 ] = HIBYTE( LOWORD( iA ) );
          pMemory[ 8 ] = LOBYTE( HIWORD( iA ) );
          pMemory[ 9 ] = HIBYTE( HIWORD( iA ) );

          int a = ( ( int ) Add - ( int ) &pMemory[ 10 ] ) - 5;

          pMemory[ 10 ] = 0xE8;
          pMemory[ 11 ] = LOBYTE( LOWORD( a ) );
          pMemory[ 12 ] = HIBYTE( LOWORD( a ) );
          pMemory[ 13 ] = LOBYTE( HIWORD( a ) );
          pMemory[ 14 ] = HIBYTE( HIWORD( a ) );

          pMemory[ 15 ] = 0x58;
          pMemory[ 16 ] = 0x58;

          pMemory[ 17 ] = 0xC3;
  }

  return pMemory;
}

int main( void ) {
  int i = 0;

  for ( i = 0; i < 4; i++ ) {
          gFunctionlist[ i ].pfnAdd = ( tAdd ) CreateAddFunction( i, 5 );

          if ( gFunctionlist[ i ].pfnAdd ) {
                ( gFunctionlist[ i ].pfnAdd ) ( 0, 0 );
                VirtualFree( gFunctionlist[ i ].pfnAdd, FUNCTION_SIZE, MEM_RELEASE );
          }
  }

  return 0;
}

Note that the call to pfnAdd has zeros as parameters but it always comes out as what the call to CreateAddFunction says.

Pierre-Marie Baty 17-05-2005 07:20

Re: Storing an array of function calls, and their params.....
 
What Maleficus is doing right now IS portable. As long as all the functions have identical arguments, storing them in the struct is perfectly doable.
Code:

typedef struct
{
        int foo;
        int (*fooFunc) (int *param1, int *param2);
        int param1;
        int param2;
} my_func_t;

Code:

// instancing
my_func_t *callerFunc;
callerFunc = new (my_func_t);
 
 
// filling in
callerFunc->fooFunc = myCoolFunc;
callerFunc->param1 = 14;
callerFunc->param2 = 22;
 
 
// calling
callerFunc->fooFunc (callerFunc->param1, callerFunc->param2);

This is 100% portable.

If you want to call funcs that have variable types of arguments instead, you can do something like this:
Code:

typedef struct
{
        union
        {
                bool bparam;
                char cparam;
                long iparam;
                float fparam;
                long long lparam;
                double dparam;
        };
        char param_type;
} param_t;
 
 
typedef struct
{
        int foo;
        int (*fooFunc) (int *param1, int *param2);
        param_t params[256];
        int param_count;
} my_func_t;

Code:

// instancing
my_func_t *callerFunc;
callerFunc = new (my_func_t);
 
 
// filling in
callerFunc->fooFunc = myCoolFunc;
callerFunc->params[0].fparam = 12.3456789f;
callerFunc->params[0].type = PARAM_FLOAT;
callerFunc->params[1].lparam = 24;
callerFunc->params[1].type = PARAM_LONG;
callerFunc->param_count = 2;
 
 
// calling
// HERE GOES DIRTY ASM CODE TO STACK UP THE ARGUMENTS AND CALL THE FUNCTION

of course THIS, will not be portable.

Maleficus 17-05-2005 11:01

Re: Storing an array of function calls, and their params.....
 
Quote:

Originally Posted by Pierre-Marie Baty
What Maleficus is doing right now IS portable. As long as all the functions have identical arguments, storing them in the struct is perfectly doable.

Good to know - thanks for clearing that up. :)

Thanks for the help guys! :D


All times are GMT +2. The time now is 04:49.

Powered by vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.