Check if a system implements a function - c
I'm creating a cross-system application. It uses, for example, the function itoa, which is implemented on some systems but not all. If I simply provide my own itoa implementation:
header.h:115:13: error: conflicting types for 'itoa'
extern void itoa(int, char[]);
In file included from header.h:2:0,
from file.c:2:0,
c:\path\to\mingw\include\stdlib.h:631:40: note: previous declaration of 'itoa' was here
_CRTIMP __cdecl __MINGW_NOTHROW char* itoa (int, char*, int);
I know I can check if macros are predefined and define them if not:
#ifndef _SOME_MACRO
#define _SOME_MACRO 45
#endif
Is there a way to check if a C function is pre-implemented, and if not, implement it? Or to simply un-implement a function?
Given you have already written your own implementation of itoa(), I would recommend that you rename it and use it everywhere. At least you are sure you will get the same behavior on all platforms, and avoid the linking issue.
Don't forget to explain your choice in the comments of your code...
I assume you are using GCC, as I can see MinGW in your path... there's one way the GNU linker can take care of this for you. So you don't know whether there is an itoa implementation or not. Try this:
Create a new file (without any headers) called my_itoa.c:
char *itoa (int, char *, int);
char *my_itoa (int a, char *b, int c)
{
return itoa(a, b, c);
}
Now create another file, impl_itoa.c. Here, write the implementation of itoa but add a weak alias:
char* __attribute__ ((weak)) itoa(int a, char *b, int c)
{
// implementation here
}
Compile all of the files, with impl_itoa.c at the end.
This way, if itoa is not available in the standard library, this one will be linked. You can be confident about it compiling whether or not it's available.
Ajay Brahmakshatriya's suggestion is a good one, but unfortunately MinGW doesn't support weak definition last I checked (see https://groups.google.com/forum/#!topic/mingwusers/44B4QMPo8lQ, for instance).
However, I believe weak references do work in MinGW. Take this minimal example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
__attribute__ ((weak)) char* itoa (int, char*, int);
char* my_itoa (int a, char* b, int c)
{
if(itoa != NULL) {
return itoa(a, b, c);
} else {
// toy implementation for demo purposes
// replace with your own implementation
strcpy(b, "no itoa");
return b;
}
}
int main()
{
char *str = malloc((sizeof(int)*3+1));
my_itoa(10, str, 10);
printf("str: %s\n", str);
return 0;
}
If the system provides an itoa implementation, that should be used and the output would be
str: 10
Otherwise, you'll get
str: no itoa
There are two really important related points worth making here along the "don't do it like this" lines:
Don't use atoi because it's not safe.
Don't use atoi because it's not a standard function, and there are good standard functions (such as snprintf) which are available to do what you want.
But, putting all this aside for one moment, I want to introduce you to autoconf, part of the GNU build system. autoconf is part of a very comprehensive, very portable set of tools which aim to make it easier to write code which can be built successfully on a wide range of target systems. Some would argue that autoconf is too complex a system to solve just the one problem you pose with just one library function, but as any program grows, it's likely to face more hurdles like this, and getting autoconf set up for your program now will put you in a much stronger position for the future.
Start with a file called Makefile.in which contains:
CFLAGS=--ansi --pedantic -Wall -W
program: program.o
program.o: program.c
clean:
rm -f program.o program
and a file called configure.ac which contains:
AC_PREREQ([2.69])
AC_INIT(program, 1.0)
AC_CONFIG_SRCDIR([program.c])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for library functions.
AH_TEMPLATE([HAVE_ITOA], [Set to 1 if function atoi() is available.])
AC_CHECK_FUNC([itoa],
[AC_DEFINE([HAVE_ITOA], [1])]
)
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
and a file called program.c which contains:
#include <stdio.h>
#include "config.h"
#ifndef HAVE_ITOA
/*
* WARNING: This code is for demonstration purposes only. Your
* implementation must have a way of ensuring that the size of the string
* produced does not overflow the buffer provided.
*/
void itoa(int n, char* p) {
sprintf(p, "%d", n);
}
#endif
int main(void) {
char buffer[100];
itoa(10, buffer);
printf("Result: %s\n", buffer);
return 0;
}
Now run the following commands in turn:
autoheader: This generates a new file called config.h.in which we'll need later.
autoconf: This generates a configuration script called configure
./configure: This runs some tests, including checking that you have a working C compiler and, because we've asked it to, whether an itoa function is available. It writes its results into the file config.h for later.
make: This compiles and links the program.
./program: This finally runs the program.
During the ./configure step, you'll see quite a lot of output, including something like:
checking for itoa... no
In this case, you'll see that the config.h find contains the following lines:
/* Set to 1 if function atoi() is available. */
/* #undef HAVE_ITOA */
Alternatively, if you do have atoi available, you'll see:
checking for itoa... yes
and this in config.h:
/* Set to 1 if function atoi() is available. */
#define HAVE_ITOA 1
You'll see that the program can now read the config.h header and choose to define itoa if it's not present.
Yes, it's a long way round to solve your problem, but you've now started using a very powerful tool which can help you in a great number of ways.
Good luck!
Related
Figure out function parameter count at compile time
I have a C library (with C headers) which exists in two different versions. One of them has a function that looks like this: int test(char * a, char * b, char * c, bool d, int e); And the other version looks like this: int test(char * a, char * b, char * c, bool d) (for which e is not given as function parameter but it's hard-coded in the function itself). The library or its headers do not define / include any way to check for the library version so I can't just use an #if or #ifdef to check for a version number. Is there any way I can write a C program that can be compiled with both versions of this library, depending on which one is installed when the program is compiled? That way contributors that want to compile my program are free to use either version of the library and the tool would be able to be compiled with either. So, to clarify, I'm looking for something like this (or similar): #if HAS_ARGUMENT_COUNT(test, 5) test("a", "b", "c", true, 20); #elif HAS_ARGUMENT_COUNT(test, 4) test("a", "b", "c", true); #else #error "wrong argument count" #endif Is there any way to do that in C? I was unable to figure out a way. The library would be libogc ( https://github.com/devkitPro/libogc ) which changed its definition of if_config a while ago, and I'd like to make my program work with both the old and the new version. I was unable to find any version identifier in the library. At the moment I'm using a modified version of GCC 8.3.
This should be done at the configure stage, using an Autoconf (or CMake, or whatever) test step -- basically, attempting to compile a small program which uses the five-parameter signature, and seeing if it compiles successfully -- to determine which version of the library is in use. That can be used to set a preprocessor macro which you can use in an #if block in your code.
I think there's no way to do this at the preprocesing stage (at least not without some external scripts). On the other hand, there is a way to detect a function's signature at compiling time if you're using C11: _Generic. But remember: you can't use this in a macro like #if because primary expressions aren't evaluated at the preprocessing stage, so you can't dynamically choose to call the function with signature 1 or 2 in that stage. #define WEIRD_LIB_FUNC_TYPE(T) _Generic(&(T), \ int (*)(char *, char *, char *, bool, int): 1, \ int (*)(char *, char *, char *, bool): 2, \ default: 0) printf("test's signature: %d\n", WEIRD_LIB_FUNC_TYPE(test)); // will print 1 if 'test' expects the extra argument, or 2 otherwise I'm sorry if this does not answer your question. If you really can't detect the version from the "stock" library header file, there are workarounds where you can #ifdef something that's only present in a specific version of that library. This is just a horrible library design. Update: after reading the comments, I should clarify for future readers that it isn't possible in the preprocessing stage but it is possible at compile time still. You'd just have to conditionally cast the function call based on my snippet above. typedef int (*TYPE_A)(char *, char *, char *, bool, int); typedef int (*TYPE_B)(char *, char *, char *, bool); int newtest(char *a, char *b, char *c, bool d, int e) { void (*func)(void) = (void (*)(void))&test; if (_Generic(&test, TYPE_A: 1, TYPE_B: 2, default: 0) == 1) { return ((TYPE_A)func)(a, b, c, d, e); } return ((TYPE_B)func)(a, b, c, d); } This indeed works although it might be controversial to cast a function this way. The upside is, as #pizzapants184 said, the condition will be optimized away because the _Generic call will be evaluated at compile-time.
I don't see any way to do that with standard C, if you are compiling with gcc a very very ugly way can be using gcc aux-info in a command and passing the number of parameters with -D: #!/bin/sh gcc -aux-info output.info demo.c COUNT=`grep "extern int foo" output.info | tr -dc "," | wc -m` rm output.info gcc -o demo demo.c -DCOUNT="$COUNT + 1" ./demo This snippet #include <stdio.h> int foo(int a, int b, int c); #ifndef COUNT #define COUNT 0 #endif int main(void) { printf("foo has %d parameters\n", COUNT); return 0; } outputs foo has 3 parameters
Attempting to support compiling code with multiple versions of a static library serves no useful purpose. Update your code to use the latest release and stop making life more difficult than it needs to be.
In Dennis Ritchie's original C language, a function could be passed any number of arguments, regardless of the number of parameters it expected, provided that the function didn't access any parameters beyond those that were passed to it. Even on platforms whose normal calling convention wouldn't be able to accommodate this flexibility, C compilers would generally used a different calling convention that could support it unless functions were marked with qualifiers like pascal to indicate that they should use the ordinary calling convention. Thus, something like the following would have had fully defined behavior in Ritchie's original C language: int addTwoOrThree(count, x, y, z) int count, x, y, z; { if (count == 3) return x+y+z; else return x+y; } int test() { return count(2, 10,20) + count(3, 1,2,3); } Because there are some platforms where it would be impractical to support such flexibility by default, the C Standard does not require that compilers meaningfully process any calls to functions which have more or fewer arguments than expected, except that functions which have been declared with a ... parameter will "expect" any number of arguments that is at least as large as the number of actual specified parameters. It is thus rare for code to be written that would exploit the flexibility that was present in Ritchie's language. Nonetheless, many implementations will still accept code written to support that pattern if the function being called is in a separate compilation unit from the callers, and it is declared but not prototyped within the compilation units that call it.
you don't. the tools you're working with are statically linked and don't support versioning. you can get around it using all kind of tricks and tips that have been mentioned, but at the end of the day they are ugly patch works of something you're trying to do that makes no sense in this context(toolkit/code environment). you design your code for the version of the toolkit you have installed. its a hard requirement. i also don't understand why you would want to design your gamecube/wii code to allow building on different versions. the toolkit is constantly changing to fix bugs, assumptions etc etc. if you want your code to use an old version that potentially have bugs or do things wrong, that is on you. i think you should realize what kind of botch work you're dealing with here if you need or want to do this with an constantly evolving toolkit.. I also think, but this is because i know you and your relationship with DevKitPro, i assume you ask this because you have an older version installed and your CI builds won't work because they use a newer version (from docker). its either this, or you have multiple versions installed on your machine for a different project you build (but won't update source for some odd reason).
If your compiler is a recent GCC, e.g. some GCC 10 in November 2020, you might write your own GCC plugin to check the signature in your header files (and emit appropriate and related C preprocessor #define-s and/or #ifdef, à la GNU autoconf). Your plugin could (for example) fill some sqlite database and you would later generate some #include-d header file. You then would set up your build automation (e.g. your Makefile) to use that GCC plugin and the data it has computed when needed. For a single function, such an approach is overkill. For some large project, it could make sense, in particular if you also decide to also code some project-specific coding rules validator in your GCC plugin. Writing a GCC plugin could take weeks of your time, and you may need to patch your plugin source code when you would switch to a future GCC 11. See also this draft report and the European CHARIOT and DECODER projects (funding the work described in that report). BTW, you might ask the authors of that library to add some versioning metadata. Inspiration might come from libonion or Glib or libgccjit. BTW, as rightly commented in this issue, you should not use an unmaintained old version of some opensource library. Use the one that is worked on. I'd like to make my program work with both the old and the new version. Why? making your program work with the old (unmaintained) version of libogc is adding burden to both you and them. I don't understand why you would depend upon some old unmaintained library, if you can avoid doing that. PS. You could of course write a plugin for GCC 8. I do recommend switching to GCC 10: it did improve.
I'm not sure this solves your specific problem, or helps you at all, but here's a preprocessor contraption, due to Laurent Deniau, that counts the number of arguments passed to a function at compile time. Meaning, something like args_count(a,b,c) evaluates (at compile time) to the constant literal constant 3, and something like args_count(__VA_ARGS__) (within a variadic macro) evaluates (at compile time) to the number of arguments passed to the macro. This allows you, for instance, to call variadic functions without specifying the number of arguments, because the preprocessor does it for you. So, if you have a variadic function void function_backend(int N, ...){ // do stuff } where you (typically) HAVE to pass the number of arguments N, you can automate that process by writing a "frontend" variadic macro #define function_frontend(...) function_backend(args_count(__VA_ARGS__), __VA_ARGS__) And now you call function_frontend() with as many arguments as you want: I made you Youtube tutorial about this. #include <stdint.h> #include <stdarg.h> #include <stdio.h> #define m_args_idim__get_arg100( \ arg00,arg01,arg02,arg03,arg04,arg05,arg06,arg07,arg08,arg09,arg0a,arg0b,arg0c,arg0d,arg0e,arg0f, \ arg10,arg11,arg12,arg13,arg14,arg15,arg16,arg17,arg18,arg19,arg1a,arg1b,arg1c,arg1d,arg1e,arg1f, \ arg20,arg21,arg22,arg23,arg24,arg25,arg26,arg27,arg28,arg29,arg2a,arg2b,arg2c,arg2d,arg2e,arg2f, \ arg30,arg31,arg32,arg33,arg34,arg35,arg36,arg37,arg38,arg39,arg3a,arg3b,arg3c,arg3d,arg3e,arg3f, \ arg40,arg41,arg42,arg43,arg44,arg45,arg46,arg47,arg48,arg49,arg4a,arg4b,arg4c,arg4d,arg4e,arg4f, \ arg50,arg51,arg52,arg53,arg54,arg55,arg56,arg57,arg58,arg59,arg5a,arg5b,arg5c,arg5d,arg5e,arg5f, \ arg60,arg61,arg62,arg63,arg64,arg65,arg66,arg67,arg68,arg69,arg6a,arg6b,arg6c,arg6d,arg6e,arg6f, \ arg70,arg71,arg72,arg73,arg74,arg75,arg76,arg77,arg78,arg79,arg7a,arg7b,arg7c,arg7d,arg7e,arg7f, \ arg80,arg81,arg82,arg83,arg84,arg85,arg86,arg87,arg88,arg89,arg8a,arg8b,arg8c,arg8d,arg8e,arg8f, \ arg90,arg91,arg92,arg93,arg94,arg95,arg96,arg97,arg98,arg99,arg9a,arg9b,arg9c,arg9d,arg9e,arg9f, \ arga0,arga1,arga2,arga3,arga4,arga5,arga6,arga7,arga8,arga9,argaa,argab,argac,argad,argae,argaf, \ argb0,argb1,argb2,argb3,argb4,argb5,argb6,argb7,argb8,argb9,argba,argbb,argbc,argbd,argbe,argbf, \ argc0,argc1,argc2,argc3,argc4,argc5,argc6,argc7,argc8,argc9,argca,argcb,argcc,argcd,argce,argcf, \ argd0,argd1,argd2,argd3,argd4,argd5,argd6,argd7,argd8,argd9,argda,argdb,argdc,argdd,argde,argdf, \ arge0,arge1,arge2,arge3,arge4,arge5,arge6,arge7,arge8,arge9,argea,argeb,argec,arged,argee,argef, \ argf0,argf1,argf2,argf3,argf4,argf5,argf6,argf7,argf8,argf9,argfa,argfb,argfc,argfd,argfe,argff, \ arg100, ...) arg100 #define m_args_idim(...) m_args_idim__get_arg100(, ##__VA_ARGS__, \ 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0, \ 0xef,0xee,0xed,0xec,0xeb,0xea,0xe9,0xe8,0xe7,0xe6,0xe5,0xe4,0xe3,0xe2,0xe1,0xe0, \ 0xdf,0xde,0xdd,0xdc,0xdb,0xda,0xd9,0xd8,0xd7,0xd6,0xd5,0xd4,0xd3,0xd2,0xd1,0xd0, \ 0xcf,0xce,0xcd,0xcc,0xcb,0xca,0xc9,0xc8,0xc7,0xc6,0xc5,0xc4,0xc3,0xc2,0xc1,0xc0, \ 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0, \ 0xaf,0xae,0xad,0xac,0xab,0xaa,0xa9,0xa8,0xa7,0xa6,0xa5,0xa4,0xa3,0xa2,0xa1,0xa0, \ 0x9f,0x9e,0x9d,0x9c,0x9b,0x9a,0x99,0x98,0x97,0x96,0x95,0x94,0x93,0x92,0x91,0x90, \ 0x8f,0x8e,0x8d,0x8c,0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x84,0x83,0x82,0x81,0x80, \ 0x7f,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,0x78,0x77,0x76,0x75,0x74,0x73,0x72,0x71,0x70, \ 0x6f,0x6e,0x6d,0x6c,0x6b,0x6a,0x69,0x68,0x67,0x66,0x65,0x64,0x63,0x62,0x61,0x60, \ 0x5f,0x5e,0x5d,0x5c,0x5b,0x5a,0x59,0x58,0x57,0x56,0x55,0x54,0x53,0x52,0x51,0x50, \ 0x4f,0x4e,0x4d,0x4c,0x4b,0x4a,0x49,0x48,0x47,0x46,0x45,0x44,0x43,0x42,0x41,0x40, \ 0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30, \ 0x2f,0x2e,0x2d,0x2c,0x2b,0x2a,0x29,0x28,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20, \ 0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10, \ 0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00, \ ) typedef struct{ int32_t x0,x1; }ivec2; int32_t max0__ivec2(int32_t nelems, ...){ // The largest component 0 in a list of 2D integer vectors int32_t max = ~(1ll<<31) + 1; // Assuming two's complement va_list args; va_start(args, nelems); for(int i=0; i<nelems; ++i){ ivec2 a = va_arg(args, ivec2); max = max > a.x0 ? max : a.x0; } va_end(args); return max; } #define max0_ivec2(...) max0__ivec2(m_args_idim(__VA_ARGS__), __VA_ARGS__) int main(){ int32_t max = max0_ivec2(((ivec2){0,1}), ((ivec2){2,3}, ((ivec2){4,5}), ((ivec2){6,7}))); printf("%d\n", max); }
using c11 standard with clang for use of strcpy_s
I'm running OS X Sierra and trying to compile a c program that uses strcpy_s, but my installed clang compiler is using the c99 standard, but from what I've read strcpy_s requires c11. Here's the code I'm trying to compile #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char source[] = "Test string"; char destination[50]; if(strcpy_s(destination, sizeof(destination), source)) printf("string copied - %s",destination); return 0; } And here's the command I'm using to compile $ clang copytest.c -o copytest copytest.c:11:5: warning: implicit declaration of function 'strcpy_s' is invalid in C99 [-Wimplicit-function-declaration] if(strcpy_s(copied_string, sizeof(copied_string), source)) ^ 1 warning generated. Undefined symbols for architecture x86_64: "_strcpy_s", referenced from: _main in copytest-e1e05a.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) I've tried compiling with the standard flag... clang -std=c11 copytest.c -o copytest but I get the same exact "invalid in c99" warning. I've also tried compiling with gcc instead, and I still get the same c99 warning. I tried upgrading via homebrew which shows the following Warning: gcc 9.2.0 is already installed and up-to-date I have clang version 9.0.0 $ clang -v Apple LLVM version 9.0.0 (clang-900.0.39.2) My xcode version is Xcode 9.2, which from everything I've read should come with c11 support. Am I doing something wrong with the compiling, is my code itself incorrect? This is the only similar question I found on here, but it didn't even have an answer. Thanks
The _s functions are an optional component of the 2011 C standard (Annex K), and, to the best of my knowledge, they have never been implemented as an integrated part of any C library. Portable code cannot rely on their availability. (Microsoft's C compilers for Windows implement an overlapping set of functions with the same names but different semantics (and sometimes even a different argument list), and at least one bolt-on implementation does exist. See this old answer, and the much longer question and answer it links to, for more detail.) Also, the _s functions do not solve the problem that they were intended to solve (unsafe string handling); it is necessary to put actual thought into a proper fix for each use of strcpy, instead of globally search-and-replacing strcpy with strcpy_s, etc., as was the hope of the authors of Annex K. If you do put appropriate amounts of thought into a proper fix, you won't need any of the _s functions to implement it. For instance, here's a fixed version of your example program: #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char source[] = "Test string"; char destination[50]; size_t srclen = strlen(source); if (srclen + 1 > sizeof destination) { fprintf(stderr, "string too long to copy - %zu bytes, need %zu\n", sizeof destination, srclen + 1); return 1; } else { memcpy(destination, source, srclen + 1); printf("string copied - %s\n", destination); return 0; } } And here's an even better version: #define _XOPEN_SOURCE 700 #include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "usage: ./test 'message of arbitrary length'\n"); return 1; } char *destination = strdup(argv[1]); if (!destination) { perror("strdup"); return 1; } printf("string copied - '%s'\n", destination); free(destination); return 0; } Therefore: Never use any of the _s functions. If you need to write a program that compiles on Windows with no warnings, put #define _CRT_SECURE_NO_WARNINGS 1 at the top of each file to make MSVC stop giving you bad advice.
If all, or even most, programmers wrote the suggested solutions above all the time, then these functions wouldn't be needed. We have a lot of evidence that many programmers do not write such careful code, going back to Spaf's notes on the Robert T Morris finger worm in the late 1980's. You also would prefer not to have to duplicate 10 lines of code for every call site of strcpy. That leads to unreadable code. More so, what zwol suggests is really just an implementation of the function he claims we don't need. A good programmer would take that, stick it in a header, and name it something helpful, maybe checked_strcpy? Or even strcpy_s? The second suggested implementation, which is purportedly better is not - it would cause an allocation when we might already have a buffer. Allocations are expensive, using this approach everywhere would be bad for perf. It also introduces new complexity because now we'd have to free every duplicated string - imagine doing that with repeated calls to strcat. There is a fairly nicely done cross-platform implementation here: https://github.com/intel/safestringlib I'm also not sure whether this is actually any different, but worth taking a look - https://github.com/coruus/safeclib
I'm implementing printf function in C/Linux
Program: #ifndef PRINTF_H #define PRINTF_H #include "my_put_char.h" int my_printf(char *str, ...); #endif This is my Header file for my function. #include <stdio.h> #include "my_put_char.h" void my_put_char(char c) { fwrite(&c, sizeof(char), 1, stdout); } This is my putchar implementation(my_put_char.c). #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include "printf.h" int my_printf(char *str, ...) { if(str == NULL) return 0; int i; char a; va_list print; va_start(print,str); for(i = 0; str[i] ; i++) { if(str[i] == '%') { i++; switch(str[i]) { case 'c': a = va_arg(print, char); my_put_char(a); break; } } } va_end(print); return 0; } At last, this is a part of my printf implementation. I'm testing with %c to display a character. When I do my_print("%c", 'd'); from main.c it compiles and displays d. But when I do my_print("%c", "hi"); , it still compiles and displays a number. Question: After(or before) writing a = va_arg(print, char); Is there a way to check whether my input is a different data type? I'm trying to display an error if my input is a different data type. I'm on this subject for 2 days and couldn't find any answer. Thank you so much for your time!
when I do my_print("%c", "hi"); , it still compiles and displays a number You've got some undefined behavior, so be scared. Your my_printf would call va_arg with an argument of the bad type (expected char promoted to int, got char*). To explain what is happening you should dive into implementation details (look into the assembler code, e.g. with gcc -Wall -fverbose-asm -O -S; study your processor, its instruction set architecture, its application binary interface and calling conventions). You don't want to do that, it could take years and is not reproducible. Read absolutely Lattner's blog on UB, right now! Then download C11 specification n1570.... You could also, with gcc, use some function attributes. Don't forget to compile with all warnings and debug info (gcc -Wall -Wextra -g) after writing a = va_arg(print, char); Is there a way to check whether my input is a different data type? No, not really and not always. But the format function attribute could help. And you could also spend months customizing GCC with your own plugin or some GCC MELT extension (that is not worth your time). Be aware of the Halting Problem and Rice's Theorem (each makes static source code program analysis so challenging). Look also into source analyzing tools like Frama-C. I'm implementing printf function BTW studying the source code of existing free software implementations of the C standard library (such as GNU glibc and musl-libc) could be inspirational; they are based upon syscalls(2).
Overriding C library functions, calling original
I am a bit puzzled on how and why this code works as it does. I have not actually encountered this in any project I've worked on, and I have not even thought of doing it myself. override_getline.c: #include <stdio.h> #define OVERRIDE_GETLINE #ifdef OVERRIDE_GETLINE ssize_t getline(char **lineptr, size_t *n, FILE *stream) { printf("getline &lineptr=%p &n=%p &stream=%p\n", lineptr, n, stream); return -1; // note: errno has undefined value } #endif main.c: #include <stdio.h> int main() { char *buf = NULL; size_t len = 0; printf("Hello World! %zd\n", getline(&buf, &len, stdin)); return 0; } And finally, example compile and run command: gcc main.c override_getline.c && ./a.out With the OVERRIDE_GETLINE define, the custom function gets called, and if it is commented out, normal library function gets called, and both work as expected. Questions What is the correct term for this? "Overriding", "shadowing", something else? Is this gcc-specific, or POSIX, or ANSI C, or even undefined in all? Does it make any difference if function is ANSI C function or (like here) a POSIX function? Where does the overriding function get called? By other .o files in the same linking, at least, and I presume .a files added to link command too. How about static or dynamic libs added with -l command line option of linker? If it is possible, how do I call the library version of getline from the overriden getline?
The linker will search the files you provide on the command line first for symbols, before it searches in libraries. This means that as soon as it sees that getline has been defined, it will no longer look for another getline symbol. This is how linkers works on all platforms. This of course has implications for your fifth point, in that there is no possibility to call the "original" getline, as your function is the original from the point of view of the linker. For the fifth point, you may want to look at e.g. this old answer.
There's no standard way to have two functions of the same name in your program, but with some UNIX-like implementations (notably GNU libc) you might be able to get away with this: #define _GNU_SOURCE #include <dlfcn.h> #include <stdio.h> ssize_t getline(char **lineptr, size_t *n, FILE *stream) { ssize_t (*realfunc)(char**, size_t *, FILE*) = (ssize_t(*)(char**, size_t *, FILE*))(dlsym (RTLD_NEXT, "getline")); return realfunc(lineptr, n, stream); } You will need to link with -ldl for this.
What is happening here is that you are relying on the behaviour of the linker. The linker finds your implementation of getline before it sees the version in the standard library, so it links to your routine. So in effect you are overriding the function via the mechanism of link order. Of course other linkers may behave differently, and I believe the gcc linker may even complain about duplicate symbols if you specify appropriate command line switches. In order to be able to call both your custom routine and the library routine you would typically resort to macros, e.g. #ifdef OVERRIDE_GETLINE #define GETLINE(l, n, s) my_getline(l, n, s) #else #define GETLINE(l, n, s) getline(l, n, s) #endif #ifdef OVERRIDE_GETLINE ssize_t my_getline(char **lineptr, size_t *n, FILE *stream) { // ... return getline(lineptr, n, stream); } #endif Note that this requires your code to call getline as GETLINE, which is rather ugly.
What you see is expected behaviour if you linking with shared libraries. Linker will just assign it to your function, as it was first. It will also be correctly called from any other external libraries functions, - because linker will make your function exportable when it will scan linking libraries. But - if you, say, have no external libraries that links to your function (so it isn't marked exportable, and isn't inserted to symbol table), and then dlopen() some library that want to use it during runtime - it will not find required function. Furthermore, if you first dlopen(RTLD_NOW|RTLD_GLOBAL) original library, every subsequent dlopen()'d library will use this library code, not yours. Your code (or any libraries that you've linked with during compilation phase, not runtime) will still stick with your function, no matter what.
Treat functions by name
Suppose you created a main() to deal with an exercise you asked your students. Every student is supposed to write their own function, with the same API. And a single file will be created, with all functions and the main calling them. Lets say: int studentname(int a, int b) is the function pattern. One way I deal with it was using a vector of pointer to functions int (*func[MAX])(). But you need to fulfill the vector one by one func[0]=studentname;. I wonder, is there a way a function can be called by its name somehow? Something like: int student1(int a , int b), student2(), etc. And in main somehow we could just call sscanf(funcname,"student%d",i); funcname();. Do you have any other idea? Maybe int studentname(int a, int b, char *fname) { strcpy(fname, "studentname"); Anything creative will do! :) Thanks! Beco PS. I tried just a vector of functions, but C won't allow me! :) int func[2]()={{;},{;}}; This way I could just give to each student a number, and voilá... But no way. It was funny though. Edited: I'm using linux. Edited 2: Thanks! I've accepted an answer that helped me, but I've also documented a complete example as an answer bellow.
Maybe a bit overcomplicating it, but spontaneous idea: Compile all student source files into one shared library with the students' functions being exports. Then enumerate all exposed functions, call and test them. As an alternative: Write a small tool that will compile all "student units" using a preprocessor define to replace a predefined function name with an unique name ("func1", "func2", etc.). Then let the tool write a small unit calling all these functions while performing tests, etc. And yet another idea: Use C++ to write a special class template that's going to register derived classes in a object factory and just embed student's code using extern "C". Depending on the implementation this might look a bit confusing and overcomplicated though. Then use the factory to create one instance of each and run the code. Example for the approach with dlopen() and dlsym() (whether only one function per library or all - doesn't matter): void *pluginlib = dlopen("student1.so", RTLD_NOW); // RTLD_NOW will load the file right away if (!pluginlib) ; // failed to load studentproc func = (studentproc)dlsym(pluginlib, "student1"); // this loads the function called "student1" if (!func) ; // failed to resolve func("hello world!"); // call the lib dlclose(pluginlib); // unloads the dll (this will make all further calls invalid)
Similar to what #Jamey-Sharp proposed: ask each student to provide .c file with entry function of a given name/signature compile each .c into a shared library, named by the student name, or given whatever unique name. This step can be easily automated with make or simple script. make a simple host application which enumerates all .so files in a given directory, and uses dlopen() and dlsym() to get to the entry point function. now you can simply call each student's implementation. BTW, that's how plug-ins are implemented usually, isn't it? Edit: Here's a working proof of concept (and a proof, that each student can use the same name of the entry point function). Here's student1.c: #include <stdio.h> void student_task() { printf("Hello, I'm Student #1\n"); } Here's student2.c: #include <stdio.h> void student_task() { printf("Hello, I'm Student #2\n"); } And here's the main program, tester.c: #include <stdio.h> #include <dlfcn.h> /* NOTE: Error handling intentionally skipped for brevity! * It's not a production code! */ /* Type of the entry point function implemented by students */ typedef void (*entry_point_t)(void); /* For each student we have to store... */ typedef struct student_lib_tag { /* .. pointer to the entry point function, */ entry_point_t entry; /* and a library handle, so we can play nice and close it eventually */ void* library_handle; } student_solution_t; void load(const char* lib_name, student_solution_t* solution) { /* Again - all error handling skipped, I only want to show the idea! */ /* Open the library. RTLD_LOCAL is quite important, it keeps the libs separated */ solution->library_handle = dlopen(lib_name, RTLD_NOW | RTLD_LOCAL); /* Now we ask for 'student_task' function. Every student uses the same name. * strange void** is needed for C99, see dlsym() manual. */ *(void**) (&solution->entry) = dlsym(solution->library_handle, "student_task"); /* We have to keep the library open */ } int main() { /* Two entries hardcoded - you need some code here that would scan * the directory for .so files, allocate array dynamically and load * them all. */ student_solution_t solutions[2]; /* Load both solutions */ load("./student1.so", &solutions[0]); load("./student2.so", &solutions[1]); /* Now we can call them both, despite the same name of the entry point function! */ (solutions[0].entry)(); (solutions[1].entry)(); /* Eventually it's safe to close the libs */ dlclose(solutions[0].library_handle); dlclose(solutions[1].library_handle); return 0; } Let's compile it all: czajnik#czajnik:~/test$ gcc -shared -fPIC student1.c -o student1.so -Wall czajnik#czajnik:~/test$ gcc -shared -fPIC student2.c -o student2.so -Wall czajnik#czajnik:~/test$ gcc tester.c -g -O0 -o tester -ldl -Wall And see it works: czajnik#czajnik:~/test$ ./tester Hello, I'm Student #1 Hello, I'm Student #2
I'd take a different approach: Require every student to use the same function name, and place each student's code in a separate source file. Write one more source file with a main that calls the standard name. Produce a separate executable from linking main.c with student1.c, then main.c with student2.c, and so on. You might be able to use wildcards in a makefile or shell script to automate this. That said, at least on Unix-like OSes, you can do what you asked for. Call dlopen(NULL) to get a handle on the symbols in the main program. Pass that handle and the function name you want to dlsym. Coerce the resulting pointer to a function pointer of the right type, and call it.
Here is an ugly preprocessor hack: #Makefile FILE_NAME=student ${FILE_NAME}: main.c cc -Wall -DFILE_NAME=\"${FILE_NAME}.c\" -o $# main.c -lm Teacher's main.c: #include <math.h> #include <stdio.h> #include FILE_NAME char *my_name(void); double my_sin(double val); int main(void) { double dd; dd = my_sin(3.1415923563); printf("%s: %f\n", my_name(), dd); return 0; } Student's .c File: #include <math.h> char * my_name(void); double my_sin(double val); char * my_name(void) { return "Wildplasser-1.0"; } double my_sin(double val) { return sin (val); } The trick lies i the literal inclusion of the student's .c file. To avoid this, you could also use a different make line, like: cc -Wall -o $# ${FILE_NAME}.c main.c -lm (and remove the ugly #include FILENAME, of course)
Thanks you all. I've accepted an answer that gave me the inspiration to solve the question. Here, just to document it, is my complete solution: File shamain.c /* Uses shared library shalib.so * Compile with: * gcc shamain.c -o shamain -ldl -Wall */ #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> int main(void) { void *libstud; int (*student[2])(int, int); char fname[32]; int i,r; libstud = dlopen("./shalib.so", RTLD_NOW); if (!libstud) { fprintf(stderr, "error: %s\n", dlerror()); exit(EXIT_FAILURE); } dlerror(); /* Clear any existing error */ for(i=0; i<2; i++) { sprintf(fname, "func%d", i); *(void **) (&student[i]) = dlsym(libstud, fname); /* c99 crap */ //student[i] = (int (*)(int, int)) dlsym(libstud, fname); /* c89 format */ } for(i=0; i<2; i++) { r=student[i](i, i); printf("i=%d,r=%d\n", i, r); } return 0; } File shalib.c /* Shared library. * Compile with: * gcc -shared -fPIC shalib.c -o shalib.so -Wall */ #include <stdio.h> int func0(int one, int jadv) { printf("%d = Smith\n", one); return 0; } int func1(int one, int jadv) { printf("%d = John\n", one); return 0; }
It is a while since I have used shared libraries, but I have a feeling you can extract named functions from a DLL/shlib. Could you create a DLL/shared library containing all of the implementations and then access them by name from the main?
Per #william-morris's suggestion, you might have luck using dlsym() to do a dynamic lookup of the functions. (dlsym() may or may not be the library call to use on your particular platform.)