Path: csiph.com!eternal-september.org!feeder.eternal-september.org!reader01.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: Calling a machine code/binary function given its address, return type, & parameter types Date: Sat, 17 Aug 2019 14:31:57 -0700 Organization: None to speak of Lines: 79 Message-ID: References: <66319c70-be79-466d-ba04-f8bb1b2d3a8a@googlegroups.com> <%EY5F.44947$665.27757@fx28.am4> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="d7e06f8f3a55978bcd7e40b372fb4e75"; logging-data="5961"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX187m7r2E9TCswrgC/qwlRVR" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) Cancel-Lock: sha1:i0MJq9UaV34Y7IzYyqcYIJ2HBeo= sha1:xdVcW7cME9G84/JwHSZu9ni3Ud0= Xref: csiph.com comp.lang.c:145703 Bart writes: > On 17/08/2019 14:58, David Williams wrote: >> I have the address of a function that has already been compiled (so >> it's now effectively a machine code routine that I've loaded into >> memory and for which I have obtained the address). I pass this >> address by value as a parameter (long or uint64_t) to my C >> subroutine. I know the return type of the function (int), and that it >> takes 4 parameters (ptr, ptr, const ptr, const ptr). How do I call >> this function from my C subroutine? >> >> I have Googled about function pointers, and I've noticed that others >> have asked a similar question, but the answers they received somehow >> don't seem directly applicable to my requirement. In any case, I've >> had no joy in my attempts at getting my (test) C subroutine to >> compile without errors. I obviously still have a weak grasp of C >> pointers and function pointers (although I'm learning!). >> >> The platform is 64-bit Linux (x86-64). > > What code did you try, and with which compiler? > > C allows functions and function pointers to be declared withour > specifying the number and types of the parameters. Example: > > #include > > int(*fnptr)(); > > int main(void) { > int result; > > result = fnptr(NULL,NULL,NULL,NULL); > } > > Since you say it takes four pointers, four pointers (in the form of > zeros or NULLs) have been supplied. NULL is a macro that expands to a null pointer constant, but a null pointer constant isn't necessarily of pointer type. (Yes, that's weird and counterintuitive, but it's true.) A null pointer constant yields a null pointer value when it's converted to a pointer type. If you call a function with no prototype, no such conversion is done. If, for example, NULL is defined as 0, int is 32 bits, and pointers are 64 bits, then fnptr(NULL,NULL,NULL,NULL) will pass 4 32-bit integer values to a function that presumably expects 4 64-bit pointer values. I *hope* that the actual types of the four parameters are known. If that's the case, then declare the function type (or, if you insist, the function pointer type) with a prototype that specifies those parameter types. With a visible prototype, NULL will be implicitly converted to the correct type. In the unlikely event that you really need to use an old-style non-prototype declaration, and you're willing to assume that all object pointers are interchangeable, then cast the NULL arguments to void*: result = fnptr((void*)NULL, (void*)NULL, (void*)NULL, (void*)NULL); But if you know the actual types, then old-style non-prototype declarations are a can of worms you don't need to open. (The OP didn't say that the arguments should be null pointers, so it's likely that the NULL stuff is irrelevant.) > But it would be much better if the actual parameter types, if known, > were provided, as then more checking can be done. For example: > > int(*fnptr)(int*, float*, char*, char*); Yes. [...] -- Keith Thompson (The_Other_Keith) kst-u@mib.org Will write code for food. void Void(void) { Void(); } /* The recursive call of the void */