Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > 'Dynamic' function calls

Reply
Thread Tools

'Dynamic' function calls

 
 
Malcolm McLean
Guest
Posts: n/a
 
      12-22-2012
On Friday, December 21, 2012 10:13:25 PM UTC, Bart wrote:
> I have a requirement to call a function where:
>
> o The function address is not known until runtime
>
> o Neither are the number and type of the parameters
>
> o Neither is the type of the function result
>
> o (And neither is the calling convention, but it will likely be one of two)
>
>

It can't be done. It's one of the few things which is possible, in fact quite
easy, in assembler, and C provides no hook into. You simply cannot build
a call list at run time.
What you need to do is to write a little assembler routine, with the C
signature
void call(void (*fptr)(void), char *signature, void *result, ...)

You probably want printf() style signatures, so to call a function taking an
integer, a double and a structure pointer

call(myfunction, "%f%d%p", 0, 0.5, 42, &mystruct);

How do you write the function call? You've got to know the C calling
convention. Typically this says "put the first few arguments in registers
and the rest on the stack". So you have to know what C regards as the stack,
and which registers take which arguments. Normally the scheme is quite simple,
real arguments go in float registers, integers and pointers in general
purpose registers.

 
Reply With Quote
 
 
 
 
Nobody
Guest
Posts: n/a
 
      12-22-2012
On Fri, 21 Dec 2012 22:13:25 +0000, BartC wrote:

> I have a requirement to call a function where:
>
> o The function address is not known until runtime
> o Neither are the number and type of the parameters
> o Neither is the type of the function result
> o (And neither is the calling convention, but it will likely be one of two)


You might want to look at libffi rather than re-inventing the wheel.

A number of high-level languages use it for their foreign function
interface (e.g. Python's ctypes module).

 
Reply With Quote
 
 
 
 
Kenny McCormack
Guest
Posts: n/a
 
      12-22-2012
In article <(E-Mail Removed)>,
Nobody <(E-Mail Removed)> wrote:
>On Fri, 21 Dec 2012 22:13:25 +0000, BartC wrote:
>
>> I have a requirement to call a function where:
>>
>> o The function address is not known until runtime
>> o Neither are the number and type of the parameters
>> o Neither is the type of the function result
>> o (And neither is the calling convention, but it will likely be one of two)

>
>You might want to look at libffi rather than re-inventing the wheel.
>
>A number of high-level languages use it for their foreign function
>interface (e.g. Python's ctypes module).
>


Yes, as others have verbosely told you, you can't do this in "Standard C".

Luckily, that is not really much of a concern, once you get into this sort
of thing.

Anyway, I've never heard of "libffi" (as posted by "Nobody"), but I've used
"ffcall" extensively - specifcally the "avcall" mechanism. I've compiled
this on lots of different architectures and it has worked fine[*].
Strongly recommended.

Google for "ffcall-1.10.tgz" - which is, I think, the latest (last) version.
[*] FWIW, it didn't compile on one specific ARM platform that I've tried
recently. I'm hoping to hear back from the author about the status of this.

--
Religion is regarded by the common people as true,
by the wise as foolish,
and by the rulers as useful.

(Seneca the Younger, 65 AD)

 
Reply With Quote
 
BartC
Guest
Posts: n/a
 
      12-22-2012
"Malcolm McLean" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> On Friday, December 21, 2012 10:13:25 PM UTC, Bart wrote:
>> I have a requirement to call a function where:
>> o The function address is not known until runtime
>> o Neither are the number and type of the parameters
>> o Neither is the type of the function result
>> o (And neither is the calling convention, but it will likely be one of
>> two)
>>

> It can't be done. It's one of the few things which is possible, in fact
> quite
> easy, in assembler, and C provides no hook into. You simply cannot build
> a call list at run time.


It looks like it. But I'd prefer to keep the program 'pure', and not use
assembler for now. (I develop on a Windows PC, but I recently tested this
~12Kloc C program on a Linux/ARM development board, and it ran perfectly**
first time! Also I don't know ARM assembly well enough...)

> How do you write the function call? You've got to know the C calling
> convention. Typically this says "put the first few arguments in registers
> and the rest on the stack". So you have to know what C regards as the
> stack,
> and which registers take which arguments. Normally the scheme is quite
> simple,
> real arguments go in float registers, integers and pointers in general
> purpose registers.


(With 32-bit systems, I found float arguments just go on the stack like
everything else. But a float result might be in a floating point register.)

What I think I'll try is to reduce the number of return types to just two:
64-bit int, and 64-bit float. And hope the 64-bit return will be meaningful
when the return type is void, or 32-bits (just ignore the top 64 or 32-bits
of the return value!).

(**Apart from being too slow. That was due to alignment problems, soon
fixed.)

--
Bartc

 
Reply With Quote
 
BartC
Guest
Posts: n/a
 
      12-22-2012


"Nobody" <(E-Mail Removed)> wrote in message
news(E-Mail Removed)...
> On Fri, 21 Dec 2012 22:13:25 +0000, BartC wrote:
>
>> I have a requirement to call a function where:
>>
>> o The function address is not known until runtime
>> o Neither are the number and type of the parameters
>> o Neither is the type of the function result
>> o (And neither is the calling convention, but it will likely be one of
>> two)

>
> You might want to look at libffi rather than re-inventing the wheel.


(I think my entire project can be considered reinventing the wheel! (And,
actually I only recently switched to using C for it instead of my own
languages.)

But, my wheels tend to be smaller, simpler, faster and (imo, and for my
purposes) better!)

> A number of high-level languages use it for their foreign function
> interface (e.g. Python's ctypes module).


I've had a quick look (at ffcall, which is where google led me), this does
seem to be depend on using 'asm'. But it's also quite a complex package,
which may or may not work under Windows, and I'll have to weigh up whether
trying to make use of it is better than just writing a few dozen lines of
repetitive C, or even a few dozen lines of my own ASM.

--
Bartc

 
Reply With Quote
 
Kenny McCormack
Guest
Posts: n/a
 
      12-22-2012
In article <vpkBs.322294$(E-Mail Removed)4>, BartC <(E-Mail Removed)> wrote:
....
>I've had a quick look (at ffcall, which is where google led me), this does
>seem to be depend on using 'asm'. But it's also quite a complex package,
>which may or may not work under Windows, and I'll have to weigh up whether
>trying to make use of it is better than just writing a few dozen lines of
>repetitive C, or even a few dozen lines of my own ASM.


ffcall (actually, specicially, avcall) works under Windows. I compiled it
for Windows long ago, using MSVC. Builds out of the box.

It has worked on every platform I've tried it on right up until I tried it
on one of my ARM boards a few days ago. Still not sure about the resolution
of that issue yet...

--
Here's a simple test for Fox viewers:

1) Sit back, close your eyes, and think (Yes, I know that's hard for you).
2) Think about and imagine all of your ridiculous fantasies about Barack Obama.
3) Now, imagine that he is white. Cogitate on how absurd your fantasies
seem now.

See? That wasn't hard, was it?

 
Reply With Quote
 
Malcolm McLean
Guest
Posts: n/a
 
      12-22-2012
On Saturday, December 22, 2012 3:21:38 PM UTC, James Kuyper wrote:
> On 12/22/2012 08:31 AM, Malcolm McLean wrote:
>
> > On Friday, December 21, 2012 10:13:25 PM UTC, Bart wrote:

>
> >> I have a requirement to call a function where:

>
> >> o The function address is not known until runtime

>
> >>

>
> >> o Neither are the number and type of the parameters

>
> >>

>
> >> o Neither is the type of the function result

>
> >>

>
> >> o (And neither is the calling convention, but it will likely be one of two)

>
> >>

>
> >>

>
> > It can't be done. It's one of the few things which is possible, in fact quite

>
> > easy, in assembler, and C provides no hook into. You simply cannot build
> > a call list at run time.

>
>
>
> If the list of possible combinations is not too big, just write down
> every possible combination, and select the appropriate one to execute.
>
>
>
> He indicated that he knew about this solution, and was trying to avoid
> it, because the list of possible combinations is fairly large - but you
> didn't quote that part of his message. The part you did quote describes
> a soluble problem (though not an easy one).
>
>

Theoretically you're right. The assembler version involves writing every
possible combination. But, if the calling convention genuinely was O(M^N)
complexity, where M was the number of types and N the number of arguments,
then a compiler would be very difficult to write.
In fact the convention will be something like "all integer and address
arguments go in r1, r2, r3, r4, then on the stack, all real arguments in
f1, f2, f3, f4 then on the stack. So it's quite easy to build a call list,
using these rules, and you can as easily pass two arguments as twenty.
Doing it from C is the O(M^N) solution.

--
Visit Malcolm's website
http://www.malcolmmclean.site1.com/www

 
Reply With Quote
 
JimB
Guest
Posts: n/a
 
      12-23-2012
BartC wrote:
> I have a requirement to call a function where:


You are lying, to yourself. You have no such requirement. I am not saying
that you are trying to maintain semblence of existence, but I'll leave that
up to "your country". "You do have a Country, boy, don't you? Well, if you
don't, we'll fix you right up with one pronto... now bend over and spread.".




 
Reply With Quote
 
glen herrmannsfeldt
Guest
Posts: n/a
 
      12-23-2012
BartC <(E-Mail Removed)> wrote:

(snip on calling functions with an unknown, at compile time, number
of arguments, possibly of unknown type.)

>> It can't be done. It's one of the few things which is possible,
>> in fact quite easy, in assembler, and C provides no hook into.
>> You simply cannot build a call list at run time.


> It looks like it. But I'd prefer to keep the program 'pure', and not use
> assembler for now. (I develop on a Windows PC, but I recently tested this
> ~12Kloc C program on a Linux/ARM development board, and it ran perfectly**
> first time! Also I don't know ARM assembly well enough...)


There are too many different ways to do it, so you can't really be sure.

For some time, at least, all the arguments were passed in the same way,
but now it is more common for some to be passed in registers. That does
complicate things.

>> How do you write the function call? You've got to know the C calling
>> convention. Typically this says "put the first few arguments in registers
>> and the rest on the stack". So you have to know what C regards as the
>> stack, and which registers take which arguments. Normally the scheme is
>> quite simple, real arguments go in float registers, integers and
>> pointers in general purpose registers.


> (With 32-bit systems, I found float arguments just go on the stack like
> everything else. But a float result might be in a floating point register.)


Even worse, if that register is on the x87 stack. You can't just ignore
it, as sometime later, likely at an unexpected time and place, a
floating point stack overflow will be detected.

I do remember random number generators for OS/360 Fortran that would
return either a floating point value between 0 and 1, or a 32 bit
integer, depending on declaring the function INTEGER or REAL.

The (assembler) function returned values in both general and floaing
point registers, and the compiler used the appropriate one.

Don't try that on IA32.

> What I think I'll try is to reduce the number of return types to just two:
> 64-bit int, and 64-bit float. And hope the 64-bit return will be meaningful
> when the return type is void, or 32-bits (just ignore the top 64 or 32-bits
> of the return value!).


Many 32 bit compilers will pass an additional argument to store the
result in if the result type is more than 32 bits. (Such as a struct.)
That might not be true for 64 bit compilers.

> (**Apart from being too slow. That was due to alignment problems, soon
> fixed.)


-- glen
 
Reply With Quote
 
glen herrmannsfeldt
Guest
Posts: n/a
 
      12-23-2012
James Kuyper <(E-Mail Removed)> wrote:

(snip regarding different function return types.)

> If the list of possible combinations is not too big, just write down
> every possible combination, and select the appropriate one to execute.


Reminds me of the PL/I ENTRY statement for functions. If different ENTRY
points have different return types, the compiler will generate code to
convert each posible type returned (argument to a RETURN statement) to
each ENTRY type. (I suppose a compiler could do enough flow analysis
to figure out which conversions could be needed, but often that
can't be done.)

> He indicated that he knew about this solution, and was trying to avoid
> it, because the list of possible combinations is fairly large - but you
> didn't quote that part of his message. The part you did quote describes
> a soluble problem (though not an easy one).


Theoretically, the number of possible return types is infinite, but
in practical cases not quite. (Mostly due to an unknown number of
levels of indirection, which can easily be handled as (void *)).

-- glen
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
This function has an onClick event that calls a function that calls This function Bob Javascript 5 10-24-2006 04:11 PM
ods calls business object then method calls ta with output params andy6 ASP .Net 2 06-09-2006 01:54 AM
How override ALL function calls? (Is there a "function call function"?) seberino@spawar.navy.mil Python 2 08-01-2005 12:38 PM
MoVoIP - FREE MOBILE Inetrnet Phone Calls - FREE Internet Phone Calls ubifone VOIP 0 07-29-2005 04:31 PM
Sequence of constructor calls and destructor calls. Honne Gowda A C++ 2 10-31-2003 09:31 AM



Advertisments