Velocity Reviews - Computer Hardware Reviews

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

Reply
Thread Tools

'Dynamic' function calls

 
 
BartC
Guest
Posts: n/a
 
      12-23-2012
"glen herrmannsfeldt" <(E-Mail Removed)> wrote in message
news:kb6k07$17l$(E-Mail Removed)...
> BartC <(E-Mail Removed)> wrote:
>
> (snip on calling functions with an unknown, at compile time, number
> of arguments, possibly of unknown type.)


>> (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.


Fortunately, I will know, at the time of the call, what the result type is.
So a float value can be 'popped' from the FPU stack, even if the function is
being called (from the target language) as a procedure with the return value
unused. (Although of course the language could get the return type wrong,
but that will be a user bug, and could happen also when declared in C.)

Slightly more tricky, are pointers to such functions, which may need the
return type and call-type contained within them to avoid problems (since
there is no static typing).

> 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.


>> 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.


That sounds unlikely for values such 64-bit versions of int types. It will
probably just use adjacent registers. Not sure about 64-bit structs though..

--
Bartc

 
Reply With Quote
 
 
 
 
BartC
Guest
Posts: n/a
 
      12-23-2012
"BartC" <(E-Mail Removed)> wrote in message
news:ku7Bs.322256$(E-Mail Removed)4...
> "glen herrmannsfeldt" <(E-Mail Removed)> wrote in message
> news:kb2ubm$4oj$(E-Mail Removed)...


>> With the cdecl convention, you should be safe passing extra arguments
>> that are ignored by the callee. The standard doesn't say anything
>> about this, though.

>
> That's a good point. On my machine, calls to normal C functions have the
> stack adjusted by the caller. So the extra params are popped.
>
> But with C calls to Win32 functions, for example, this is handled by the
> callee, which will only pop what are expected.


Looking at the output of gcc under Windows, this seems to do the opposite of
what I expected:

Calls to normal C functions, have the stack adjusted by the callee.

Calls to Windows functions (__stdcall) have the stack adjusted by the
caller. Yet I can call the same functions from other languages, and I don't
need to do this!

Furthermore, when obtaining the address of a __stdcall function dynamically
(GetProcAddress), it seems to work just as well whether I declare the
function pointer as __stdcall or not. All very strange. Anyway it works at
the minute (based on my extensive tests of calling one function..).

(Example

#include <windows.h>

int main (void) {
int fnaddr;

fnaddr=(int)GetProcAddress(LoadLibrary("user32")," MessageBoxA");
if (fnaddr==0) exit(0);

((int __stdcall (*)(int,char*,char*,int))fnaddr) (0,"With
__stdcall","one",0);
((int (*)(int,char*,char*,int))fnaddr) (0,"Without __stdcall","two",0);

}


--
Bartc

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

....
> 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 *)).


Bart's original message said:
"The function return type can be similarly limited to 4 possibilities:
none, 32-bit, 64-bit, and 64-bit floating point".

That's far less than infinite, and none of those types is a pointer
type, so levels of indirection don't come into play.
--
James Kuyper
 
Reply With Quote
 
Philip Lantz
Guest
Posts: n/a
 
      12-24-2012
BartC wrote:
>
> "BartC" <(E-Mail Removed)> wrote in message
> news:ku7Bs.322256$(E-Mail Removed)4...
> > "glen herrmannsfeldt" <(E-Mail Removed)> wrote in message
> > news:kb2ubm$4oj$(E-Mail Removed)...

>
> >> With the cdecl convention, you should be safe passing extra arguments
> >> that are ignored by the callee. The standard doesn't say anything
> >> about this, though.

> >
> > That's a good point. On my machine, calls to normal C functions have the
> > stack adjusted by the caller. So the extra params are popped.
> >
> > But with C calls to Win32 functions, for example, this is handled by the
> > callee, which will only pop what are expected.

>
> Looking at the output of gcc under Windows, this seems to do the opposite of
> what I expected:
>
> Calls to normal C functions, have the stack adjusted by the callee.
>
> Calls to Windows functions (__stdcall) have the stack adjusted by the
> caller. Yet I can call the same functions from other languages, and I don't
> need to do this!
>
> Furthermore, when obtaining the address of a __stdcall function dynamically
> (GetProcAddress), it seems to work just as well whether I declare the
> function pointer as __stdcall or not. All very strange. Anyway it works at
> the minute (based on my extensive tests of calling one function..).
>
> (Example
>
> #include <windows.h>
>
> int main (void) {
> int fnaddr;
>
> fnaddr=(int)GetProcAddress(LoadLibrary("user32")," MessageBoxA");
> if (fnaddr==0) exit(0);
>
> ((int __stdcall (*)(int,char*,char*,int))fnaddr) (0,"With
> __stdcall","one",0);
> ((int (*)(int,char*,char*,int))fnaddr) (0,"Without __stdcall","two",0);
>
> }


I would bet that the second of these two calls is messing up the stack,
but since it is followed by
mov esp, ebp
pop ebp
ret
you don't observe a problem.

I suspect that if you try making the incorrect call in a more complex
program, you will discover that it doesn't work right after all.
 
Reply With Quote
 
BartC
Guest
Posts: n/a
 
      12-24-2012
"Philip Lantz" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)-september.org...
> BartC wrote:


>> Calls to normal C functions, have the stack adjusted by the callee.
>>
>> Calls to Windows functions (__stdcall) have the stack adjusted by the
>> caller. Yet I can call the same functions from other languages, and I
>> don't
>> need to do this!
>>
>> Furthermore, when obtaining the address of a __stdcall function
>> dynamically
>> (GetProcAddress), it seems to work just as well whether I declare the
>> function pointer as __stdcall or not. All very strange. Anyway it works
>> at
>> the minute (based on my extensive tests of calling one function..).


>> ((int __stdcall (*)(int,char*,char*,int))fnaddr) (0,"With
>> __stdcall","one",0);
>> ((int (*)(int,char*,char*,int))fnaddr) (0,"Without __stdcall","two",0);
>>
>> }

>
> I would bet that the second of these two calls is messing up the stack,
> but since it is followed by
> mov esp, ebp
> pop ebp
> ret
> you don't observe a problem.
>
> I suspect that if you try making the incorrect call in a more complex
> program, you will discover that it doesn't work right after all.


The mystery seems deeper than that. I've been making calls to Win32
functions, via my own language and compiler, for years. This language needs
to use add esp,N after every call to a C library function, but doesn't need
it after a __stdcall (eg. Win32) call.

This language also doesn't use mov esp,ebp at the of a function, but add
esp,N (N being the number of bytes in the stack frame), so would be
sensitive to rogue values of stack pointer. And also, for last few months
the language has depended on the same gcc linker (and presumably the same C
library) as has built the above example!

--
Bartc

 
Reply With Quote
 
SG
Guest
Posts: n/a
 
      12-24-2012
Am 21.12.2012 23:13, schrieb BartC:
> 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)


Maybe libffi is what you are looking for.

Cheers!
SG
 
Reply With Quote
 
JimB
Guest
Posts: n/a
 
      12-31-2012
Shao Miller wrote:
> On 12/21/2012 19:20, glen herrmannsfeldt wrote:
>>
>> For C functions that aren't varargs, it would be possible to use
>> the stdcall convention, though I don't know of any compilers that do.
>>

>
> stdcall is used pretty frequently in Microsoft-land. - Shao


You are a fucing idiot, why don't you just shut up.


 
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