![]() |
'Dynamic' function calls
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) So nothing too difficult... But I want to avoid sprawling code that tries to enumerate all the possibilities. (This to help an interpreted language call a foreign function in a run-time-loaded dynamic library. It only needs to work on two platforms both of which have a natural 32-bit int size) The input parameters are easily dealt with, by letting all possibilities be represented by an array of 0 to N 32-bit ints. N can be at least 12. But I can't see any way in C of calling a function pointer with a variable number of parameters, without writing at least N+1 different calls. The function return type can be similarly limited to 4 possibilities: none, 32-bit, 64-bit, and 64-bit floating point (I think the latter uses a different return register on the two platforms I have in mind). While the call types will be C-language (I assume the library will use the same convention as my C program), and whatever the OS might use. So I can probably do this with only 13 x 4 x 2 lots of calls (about 100). But if there's any way of simplifying this, without dropping into assembly code, that would be appreciated! -- Bartc |
Re: 'Dynamic' function calls
"BartC" <bc@freeuk.com> writes:
> The input parameters are easily dealt with, by letting all > possibilities be represented by an array of 0 to N 32-bit ints. N > can be at least 12. But I can't see any way in C of calling a > function pointer with a variable number of parameters, without > writing at least N+1 different calls. What happens if you call a two-parameter function with (a1, a2, a3, a4, a5, ...., aN) ? We are way out of defined territory here, but most ABI's I know of, would simply ignore the extra parameters. So you might be lucky that your supported platforms' ABI would accept such an call. -- /Wegge Leder efter redundant peering af dk.*,linux.debian.* |
Re: 'Dynamic' function calls
"Anders Wegge Keller" <wegge@wegge.dk> wrote in message news:87pq23hw6z.fsf@huddi.jernurt.dk... > "BartC" <bc@freeuk.com> writes: > >> The input parameters are easily dealt with, by letting all >> possibilities be represented by an array of 0 to N 32-bit ints. N >> can be at least 12. But I can't see any way in C of calling a >> function pointer with a variable number of parameters, without >> writing at least N+1 different calls. > > What happens if you call a two-parameter function with (a1, a2, a3, > a4, a5, ...., aN) ? > > We are way out of defined territory here, but most ABI's I know of, > would simply ignore the extra parameters. So you might be lucky that > your supported platforms' ABI would accept such an call. I was wondering that, but didn't dare ask! On my main machine (Windows) params are pushed right-to-left which helps. The other (Linux with gcc) I'll have to check out, although I haven't even sorted the mysteries of dlopen() yet.. Will need to do some tests I think. (I don't need to push 12 params every time; either 4, 8 or 12 for example will reduce the code considerably). -- Bartc |
Re: 'Dynamic' function calls
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) > > So nothing too difficult... But I want to avoid sprawling code that tries to > enumerate all the possibilities. This isn't that unusual. The UNIX dlsym() returns all objects, including function addresses as void*. > (This to help an interpreted language call a foreign function in a > run-time-loaded dynamic library. It only needs to work on two platforms both > of which have a natural 32-bit int size) > > The input parameters are easily dealt with, by letting all possibilities be > represented by an array of 0 to N 32-bit ints. N can be at least 12. But I > can't see any way in C of calling a function pointer with a variable number > of parameters, without writing at least N+1 different calls. I have a library that uses dlsym() to find named functions in an XML-RPC call. In my case, I do build an arrays of 0,1,2 and 3 parameter callers. > The function return type can be similarly limited to 4 possibilities: none, > 32-bit, 64-bit, and 64-bit floating point (I think the latter uses a > different return register on the two platforms I have in mind). While the > call types will be C-language (I assume the library will use the same > convention as my C program), and whatever the OS might use. In my case, I use seven return types used by XML-RPC, which does result in quite a large matrix. The code (using C++ templates) is quite compact, but takes a while to compile! This isn't usually a problem as it just keeps one core busy while the rest of the library compiles on the rest.. -- Ian Collins |
Re: 'Dynamic' function calls
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) > > So nothing too difficult... But I want to avoid sprawling code that tries > to enumerate all the possibilities. > > (This to help an interpreted language call a foreign function in a > run-time-loaded dynamic library. It only needs to work on two platforms > both of which have a natural 32-bit int size) > > The input parameters are easily dealt with, by letting all possibilities > be represented by an array of 0 to N 32-bit ints. N can be at least 12. > But I can't see any way in C of calling a function pointer with a variable > number of parameters, without writing at least N+1 different calls. > > The function return type can be similarly limited to 4 possibilities: > none, 32-bit, 64-bit, and 64-bit floating point (I think the latter uses a > different return register on the two platforms I have in mind). While the > call types will be C-language (I assume the library will use the same > convention as my C program), and whatever the OS might use. > > So I can probably do this with only 13 x 4 x 2 lots of calls (about 100). > But if there's any way of simplifying this, without dropping into assembly > code, that would be appreciated! Is it possible to wrap that function? If that is possible then you could solve the parameters issue by using a struct that stores a list of parameters to pass an indeterminate number of parameters, and for the return type you could use void pointer passed as a parameter and then let the return value of the wrapper point which data type was passed, to be able to cast that void pointer to something meaningful. For example: <pseudo-ish code> struct Params { int n; int *parameters; }; enum WrapperReturnType { WRT_VOID, WRT_FP32, WRT_FP64 }; enum WrapperReturnType wrapper(struct Params *parameters, void *returned_value); </pseudo-ish code> Rui Maciel |
Re: 'Dynamic' function calls
On 12/21/2012 17:13, 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) > > So nothing too difficult... But I want to avoid sprawling code that > tries to > enumerate all the possibilities. > > (This to help an interpreted language call a foreign function in a > run-time-loaded dynamic library. It only needs to work on two platforms > both > of which have a natural 32-bit int size) > > The input parameters are easily dealt with, by letting all possibilities be > represented by an array of 0 to N 32-bit ints. N can be at least 12. But I > can't see any way in C of calling a function pointer with a variable number > of parameters, without writing at least N+1 different calls. > > The function return type can be similarly limited to 4 possibilities: none, > 32-bit, 64-bit, and 64-bit floating point (I think the latter uses a > different return register on the two platforms I have in mind). While the > call types will be C-language (I assume the library will use the same > convention as my C program), and whatever the OS might use. > > So I can probably do this with only 13 x 4 x 2 lots of calls (about 100). > But if there's any way of simplifying this, without dropping into assembly > code, that would be appreciated! > It doesn't seem that portability is a concern, so perhaps you can investigate the possibility of building an automatic VLA inside some curly braces and then passing _no_ arguments, then see if the called function picks up its arguments from the VLA in the caller. If it works, it might reduce the combinations to 4 x 2. (A VLA could even be one of 'unsigned char' and populated with the object representations of "the parameters" the called function is expecting, that way, all "params" needn't have the same size.) I haven't used this strategy before on any platform, so please consider that when considering the potential for wasting time. :) - Shao Miller |
Re: 'Dynamic' function calls
Anders Wegge Keller <wegge@wegge.dk> wrote:
> "BartC" <bc@freeuk.com> writes: >> The input parameters are easily dealt with, by letting all >> possibilities be represented by an array of 0 to N 32-bit ints. N >> can be at least 12. But I can't see any way in C of calling a >> function pointer with a variable number of parameters, without >> writing at least N+1 different calls. > What happens if you call a two-parameter function with (a1, a2, a3, > a4, a5, ...., aN) ? > We are way out of defined territory here, but most ABI's I know of, > would simply ignore the extra parameters. So you might be lucky that > your supported platforms' ABI would accept such an call. For K&R C, that pretty much has to be true for varargs to work. With ANSI C, at least C89, it only has to be true for actual varargs routines. A completely different calling convention could be used for non-varargs functions. But on most systems the same convention is used. The 8086 (and successors) have a RET (return) instruction that can also pop a specified number of (16 bit) words off the stack. The early 8086 compilers, for Fortran and Pascal, used this, as they don't have any variable argument calls. That is, the callee pops the arguments off the stack. In the transition to 32 bit code, this evolved to the stdcall ( http://en.wikipedia.org/wiki/Stdcall#stdcall ) convention. When C compilers started to appear for 8086, with the requirement to support varargs (and before ANSI C), a new calling convention was defined such that the caller (which knows the number of arguments) pops them off the stack. Along with the evolution (and naming) of stdcall, this evolved to be named cdecl, where the caller pops the arguments. Some compilers allow one to specify the calling convention with the function prototype (or definition), such that they can be mixed within a program. 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. 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. -- glen |
Re: 'Dynamic' function calls
"glen herrmannsfeldt" <gah@ugcs.caltech.edu> wrote in message
news:kb2ubm$4oj$1@speranza.aioe.org... > Anders Wegge Keller <wegge@wegge.dk> wrote: >> "BartC" <bc@freeuk.com> writes: >>> But I can't see any way in C of calling a >>> function pointer with a variable number of parameters, without >>> writing at least N+1 different calls. > >> What happens if you call a two-parameter function with (a1, a2, a3, >> a4, a5, ...., aN) ? > When C compilers started to appear for 8086, with the requirement > to support varargs (and before ANSI C), a new calling convention > was defined such that the caller (which knows the number of arguments) > pops them off the stack. > > Along with the evolution (and naming) of stdcall, this evolved > to be named cdecl, where the caller pops the arguments. > > Some compilers allow one to specify the calling convention with > the function prototype (or definition), such that they can be > mixed within a program. > > 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. > > 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. (And a test showed this doesn't work. In any case, there is a further problem that the names of such functions, when passed to the linker, have the number of parameter bytes encoded into them! Circumventing that just caused a crash.) -- Bartc |
Re: 'Dynamic' function calls
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 |
Re: 'Dynamic' function calls
Shao Miller <sha0.miller@gmail.com> 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 Yes, but are there C compilers that use stdcall without any special attributes or compiler options requesting it? Even more, that use it for libc? I know it is common for Windows system calls, but then since it is closed source we don't know that it is C. -- glen |
| All times are GMT. The time now is 08:58 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.