Call function at runtime

L

leaf

Hi,

How to call function at runtime,
based on a struct that contains the information for the function call:
struct func_to_call {
int function_id; // function id to call
unsigned int nparams; // number of parameters
unsigned long* parameter; // the parameter(s) to pass
}

to be passed to some function like this one:

call_function( int id, unsigned int nparams, unsigned long* params )
{
// ???
}

*as you can see functions have different number of parameters ( but all
are of type ULONG )
* function are called from a DLL.
* should i call_function via ordinal number?
 
V

Victor Bazarov

leaf said:
How to call function at runtime,
based on a struct that contains the information for the function call:
struct func_to_call {
int function_id; // function id to call
unsigned int nparams; // number of parameters
unsigned long* parameter; // the parameter(s) to pass
}

to be passed to some function like this one:

call_function( int id, unsigned int nparams, unsigned long* params )
{
// ???
}

*as you can see functions have different number of parameters ( but all
are of type ULONG )
* function are called from a DLL.
* should i call_function via ordinal number?

I think you need to invest a bit more time at reading about the things
known as "interpreters". Mechanisms for function invocation are very
implementation- and system-specific, if you want to be reasonably
sophisticated.

In most simple cases you create a table of addresses of the functions you
expect to call and then match the function address (pointer) to the ID you
assigned to it.

V
 
N

n2xssvv g02gfr12930

leaf said:
Hi,

How to call function at runtime,
based on a struct that contains the information for the function call:
struct func_to_call {
int function_id; // function id to call
unsigned int nparams; // number of parameters
unsigned long* parameter; // the parameter(s) to pass
}

to be passed to some function like this one:

call_function( int id, unsigned int nparams, unsigned long* params )
{
// ???
}

*as you can see functions have different number of parameters ( but all
are of type ULONG )
* function are called from a DLL.
* should i call_function via ordinal number?

Why not just use an STL vector for the parameters and either an array
or STL map of function pointers. I've used methods like this without
much difficulty, (OK I'm geeky about C++), so I suggest you learn about
STL vectors and function pointers.

JB
 
L

leaf

this article:
http://www.drizzle.com/~scottb/gdc/fubi-paper.htm

seems to be a solution to me,
its about 'Function Binding System'

using a bit of assembly, it calls a function with variable arguments i
think,
here's the code snippet:

DWORD Call_cdecl( const void* args, size_t sz, DWORD func )
{
DWORD rc; // here's our return value...
__asm
{
mov ecx, sz // get size of buffer
mov esi, args // get buffer
sub esp, ecx // allocate stack space
mov edi, esp // start of destination stack frame
shr ecx, 2 // make it dwords
rep movsd // copy params to real stack
call [func] // call the function
mov rc, eax // save the return value
add esp, sz // restore the stack pointer
}
return ( rc );
}

*as you can see its pretty much the one that i need i think,
the line that needs attention is this:
call [func] // call the function

what reference will ensure that that line would call the right
function?
from where?
 
L

leaf

i may have slipped in reading, but i think it uses symbol names
exported with dllexport to allow binding by name to exported symbols?
 
V

Victor Bazarov

leaf said:
this article:
http://www.drizzle.com/~scottb/gdc/fubi-paper.htm

seems to be a solution to me,
its about 'Function Binding System'

using a bit of assembly, it calls a function with variable arguments i
think,
here's the code snippet:

DWORD Call_cdecl( const void* args, size_t sz, DWORD func )
{
DWORD rc; // here's our return value...
__asm

First of all, it's "asm" and not "__asm". Second, whatever you think you
know about assembly, has no relevance here. In C++ assembly code is not
standardized. It's totally implementation- and platform-specific.
[...]

*as you can see its pretty much the one that i need i think,
the line that needs attention is this:
call [func] // call the function

what reference will ensure that that line would call the right
function?
from where?

That is _not_defined_. Ask in a newsgroup that deals with your compiler
or with your platform, or both.

V
 
V

Victor Bazarov

leaf said:
i may have slipped in reading, but i think it uses symbol names
exported with dllexport to allow binding by name to exported symbols?

Now you're totally off topic.
 
K

Kaz Kylheku

leaf said:
Hi,

How to call function at runtime,
based on a struct that contains the information for the function call:
struct func_to_call {
int function_id; // function id to call
unsigned int nparams; // number of parameters
unsigned long* parameter; // the parameter(s) to pass
}

This is not portable in portable C++. The number of functions passed in
a function call are determined at compile time, and comiple time is
something that occurs prior to execution time. C++ does not define any
way of dynamic compiling and loading.

What you can do is pre-compile some cooked function calls, and have a
big switch statement which selects one of these calls based on the
parameters.

For instance, suppose all the parameters are restricted to type int,
and the only variation is in the parameter number. Then, given a
pointer to the function ptr, and an array of integer arguments
int_arg[], you can do something like:

switch (number_of_arguments) {
case 0:
{
void (*func)() = (void (*)()) ptr;
func();
}
break;
case 1:
{
void (*func)(int) = (void (*)(int)) ptr;
func(int_arg[0]);
}
break;
case 2:
{
void (*func)(int, int) = (void (*)(int, int)) ptr;
func(int_arg[0], int_arg[1]);
}
break;
/* ... other cases ... */
}

This kind of "glue" code can quickly explode in size, since you have to
write the source code for every kind of binary interface you want to
call, include it in the body of the program, and have a way to route
control to it.

There is a library (GNU GPL'ed though!) for constructing C function
argument lists dynamically and calling functions. The name of this
library is "libavcall" and it was originally written by Bill Triggs.

This library defines a set of macros which, loosely speaking, function
as "opposites" to the standard <stdarg.h> macros va_list, va_arg. That
is why the letter "AV" are used to name the library: VA backwards.

When you construct a list with a specific return type and arguments, it
is automagically copmatible with a function which has that signature,
so then all that is needed is a pointer to that function and you can
call it.

The avcall library is not written portably. It contains a lot of
compiler and platform specific code. It has to understand the calling
conventions of the architecture and operating system platform, so that
given any dynamically constructed av_list, it constructs the right kind
of function calling linkage and performs the right kind of cleanup
afterward.
 
L

leaf

One question:
When a you 'link' a DLL lib ( static linking ) into a Win32 application
for example;
can we call the functions ( we know that exist in the DLL ) via some
low-level means?
will the exported functions have an 'address/pointer or something' with
the application's process space?

to note:
functions that i need to call are from a DLL, exported using dllexport
for instance.
 
K

Kaz Kylheku

leaf said:
One question:

.... for a Win32 newsgroup, not for here.
When a you 'link' a DLL lib ( static linking ) into a Win32 application
for example;

DLL is not static linking (note the 'D'). The DLL's that are specified
on the linker command line when the program is built are still
dynamically loaded with LoadLibrary(). This is called "load time
dynamic linking" by MSDN. That term is used in the FreeLibrary page for
instance.

LoadLibrary will find an library that is already loaded and properly
increment the reference count on the handle. when you are done with
that reference, use FreeLibrary to drop it. This is true whether the
library was load-time linked or whether it was explicitly loaded by a
call to LoadLibrary().

There is also GetModuleHandle which doesn't increment the module
reference count. This is probably okay for those load-time linked
libraries which can be counted upon to remain valid over the lifetime
of the program.
will the exported functions have an 'address/pointer or something' with
the application's process space?

Yes, accessible by GetProcAddress
to note:
functions that i need to call are from a DLL, exported using dllexport
for instance.

That doesn't matter. The issues are the same. You end up with a pointer
to the function. Unless you have some dynamic calling mechanism like
that avcall library, you have to cast that pointer to the right type
and call it with the right arguments. That cast and call are written in
your program and compiled. If you have a small repertoire of type
signatures, you can just write the glue code.
 
L

leaf

I think you're right, that would end up to a pointer to a function.
What i'm thinking before was the ".lib" file.... sorry.

Now, to get back with the real problem
consider this code:

DispatchFunc( 543, (LPVOID) theParams );
explanation: call function #543 and pass these parameters (theParams )
it knows about the number of parameters as it is stored in a table

If you want you can check this out:
http://www.drizzle.com/~scottb/gdc/fubi-paper.htm
to check about the actual implementation of that function.

Why am i doing this?
1) There are so many functions in the DLL, all i have is the
documentation of the function prototypes ( argument list etc. )
2) FuBi ( Function Binding System ) has promises. It can 'get' the
exported function in a DLL and store it on a Table of functions
(g_Functions)
3) All i have to do is to call DispatchFunction( int serialID, const
void* params )
*g_Functions table is filled at Application startup, i think

Where did i got the data to pass to 'int serialID' and 'const void*
params'?
Its stored in a binary file, which extracted and eventually will have
those data....
 
K

Kaz Kylheku

leaf said:
Where did i got the data to pass to 'int serialID' and 'const void*
params'?

Uh, I don't have time to read the whole paper, but it's describing a
crude RPC mechanism which doesn't deal with issues of passing or
returning reference data, or marshalling data between different machine
architectures.

The serialID comes over the network. It is computed on the client side
by fetching the instruction pointer and searching through the client's
g_Functions table! The serialID travels over the network to the RPC
server, where it is used to locate the corresponding and fetch its
machine address.

The client-side functions are just RPC stubs, and so the g_Functions
array in the client contains the addresses of these RPC stubs. On the
server side, the corresponding array (which must be constructed in
exactly the same order) contains the real functions.

Each stub can find itself in the client-side array by computing its own
address from the instruction pointer register and searching through the
table for the nearest address. This is done by the FindFunction()
routine which is not shown. And that is how each stub knows its own
serialID, and also the meta-information about itself, such as the size
of its argument list on the stack.

The void * parameter is just the packaged up arguments which also come
from the client. It's crude. The client stub information from its
function descriptor to know how big the arguments are, and simply takes
a snapshot off the stack. This is sent as part of the RPC packet to the
other side, which copies it to the stack as part of the function
calling mechanism.

All this stuff is quite so Windows-specific, you have to wonder why the
guy is trying to reinvent Microsoft RPC. Even Microsoft weren't that
dumb; they took their RPC from the Distributed Computing Environment
(DCE) project.

If you don't want that, there are other RPC implementations out there,
complete with interface description languages. No need to hack like
this.
From the "Further Work" paper:

you could create a tool to scan windows.h and other header files
and extract the unmangled function prototypes, converting them
into a type library. "

Yes, indeed. You could re-invent RPC-type tools which already exist.
And that's just your "Further Work". Doh!

For instance:

http://www.swig.org/exec.html

If you have work to do, don't waste your time on undergraduate-level
"oh my god I've discovered you can memcpy pieces of a stack to do RPC"
type of stuff.
 
L

leaf

Both can be regarded as scripting languages, but wow about the
automatic mapping of exported function from a DLL to the Application
(Win32)? with the g_Functions table? ( during application start-up i
presume )

Yes, indeed you're right about the RPC-like behaviour of it with
regards to calling functions over the network...

I tried to see SWIG, i think it gives me the responsibility to create
an "Interface file" to w/c function prototypes are declared,

but
In my target DLL there have function like:
bool set_hardware_setting_a( int register, unsigned long data );
unsigned long read_data_from( int register );
void start_clocking()
etc. <about 800-1000 functions more...>

I could almost rewrite the whole DLL-code by doing that,
What could you suggest?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,772
Messages
2,569,593
Members
45,110
Latest member
OdetteGabb
Top