How should I organize this C project - c

I am doing this programming assignment in C. But I am confused as to how to organize it.
So, here is the situation. I have two tree implementations and declare their struct/includes/function prototypes and so on in two separate header files. Then I have two c source code for the two implementations. Now here comes the problem. I have one test c file (only one main function for running tests) for the ADTs of Trees. Since the two implementations are going to use the same test. How can I avoid making two copies of the same main.c file? when I include the header file of tree implementation1, I can do gcc Tree_implementation1.c main.c. But to do implementation2, I have to got back in the main source file and manually change the include to tree implementation2, and then I can use the same compilation command. How do I work around this to toggle between the two implementations with only one main.c?

Use the preprocessor and a constant that you can set on the command line:
In your main.c:
#ifdef TREE_IMPL1
#include "TreeImplementation1.h"
#else
#include "TreeImplementation2.h"
#endif
// ...
int main(int argc, char **argv)
{
#ifdef TREE_IMPL1
// code for testing TreeImplementation1
#else
// code for testing TreeImplementation2
#endif
}
When you compile, pass or omit TREE_IMPL1 on the command line, or set it in your IDE:
gcc -DTREE_IMPL1 main.c ...

Do your implementations have the same name? They shouldn't.
If (or when) they don't have the same name, you can just include both headers in main.c and test either one depending on some preprocessor directive.
//main.c
#include "Tree_implementation1.h"
#include "Tree_implementation2.h"
int main()
{
#ifdef TEST_FIRST
testFirstTree(); //declared in Tree_implementation1.h
#else
testSecondTree(); //declared in Tree_implementation2.h
#endif
return 0;
}

Another solution for your problem is using of dynamic interface.
Work the way like that:
#include "Imp_1.h"
#include "Imp_2.h"
typedef void (*TreeFunctionType1)(Tree,param);
typedef void (*TreeFunctionType2)(Tree);
typedef struct ITree
{
TreeFunctionType1 func1;
TreeFunctionType2 func2;
}ITree;
static ITree _Itree={0};
void SetImp(TreeFunctionType1 f1,TreeFunctionType2 f2)
{
tree.func1 = f1;
tree.func2 = f2;
}
/*Use only this functions in your Tests code*/
//{
void Func1(Tree tree,Param param)
{
(*_Itree.func1)(tree,param);
}
void Func2(Tree tree)
{
(*_Itree.func2)(tree);
}
//}
int main(int argc, char const *argv[])
{
SetImp(Imp_1_f1,Imp_1_f2);
TestCode();
SetImp(Imp_2_f1,Imp_2_f2);
TestCode();
return 0;
}

Related

Is there a method for versioning header and library dependencies in C?

We have a repo that contains library functions for example (gcc is used to compile and link).
//print.h
#ifndef __PRINT_H_
#define __PRINT_H_
#define MAX_ARRAY 10
void print_hex(int cal[]);
#endif
// print.c
#include <stdio.h>
void print_hex(int val[]) {
for (int I=0;I<MAX_ARRAY;I++) {
printf("%i\n",val[I]);
}
}
The above is compiled into a libprint.a.1.0.0. My app is then compiled using this library
//main.c
#include "print.h"
int main(int argc, int arg[]) {
int vals[MAX_ARRAY];
memset(vals,8,MAX_ARRAY*sizeof(int));
print_hex(vals);
return 0;
}
And everything is fine and works (assuming have typed the above out correctly). But then someone decides to make a change in the library where someone Makes the following change.
//print.h
...
#define MAX_ARRAY 50
...
The library is recompiled to libprint.a.1.1.0
This new static library is now used when compiling and linking our main.c. However, the new print.h was not copied to the include directory so the main.c is using an old print.h where MAX_ARRAY is smaller.
Now in this case we might get any behaviour as the print function runs off the end of the passed in array. As a user of the library there is no way to necessarily know that the header file is wrong until I compile and run the application, or perhaps even hours of running when the program starts to go crazy.
What is the standard way to avoid this issue?
Is there a way to add a version to a header file to ensure the correct library is linked?
I realise I could do this by creating a new function in print.c called get_version(), and use that in main.c to check against some defines in print.h to ensure veracity but I was wondering if there was a way without the user application having to specifically check library and header versions at run time.
Yes. And don't do it.
The libfuse library uses a macro FUSE_USE_VERSION that should be defined by the client to differentiate between different versions. Internally it works similar to feature_test_macros.
So in your library it would look like:
print.h:
#ifndef __PRINT_H_
#define __PRINT_H_
#if PRINT_USE_VERSION == 1
#define MAX_ARRAY 10
void print_hex_version_1(int cal[]);
static inline
void print_hex(int cal[]) {
print_hex_version_1(val);
}
#elif PRINT_USE_VERSION == 2
#define MAX_ARRAY 50
void print_hex_version_2(int cal[]);
static inline
void print_hex(int cal[]) {
print_hex_version_2(val);
}
#else
#error unknown PRINT_USE_VERSION
#endif
#endif
print_version_1.c:
#define PRINT_USE_VERSION 1
#include <stdio.h>
void print_hex_version_1(int val[]) {
for (int I=0;I<MAX_ARRAY;I++) {
printf(ā€œ%i\nā€,val[I]);
}
}
print_version_2.c:
#define PRINT_USE_VERSION 2
#include <stdio.h>
void print_hex_version_2(int val[]) {
for (int I=0;I<MAX_ARRAY;I++) {
printf(ā€œ%i\nā€,val[I]);
}
}
Or similar, hope you'll you get the idea. Using this method you can distribute all possible versions of your library at once. And clients can link against multiple versions of your library. Which ends up being spaghetti code, unstable, unreliable, unfixable and unmaintainable.
On a global scale, it makes no sense. Just create a api that isn't dependent on a macro definition and take the array size as an argument. Check if the size of the array is equal to some predefined value and notify your client with error code that he did something wrong.

Check Unit testing in C: Best way to test static methods

I am using Check framework do to unit testing of my C code, and I couldn't find a proper way to test the static methods.
My work around, is not ideal at all and would like if someone can point me in the right direction on how to do it properly. My work around is simply by add #ifdef macro that changes the static methods to extern in case I pass -D DEBUG at compile time.
In the source file
#ifdef DEBUG
unsigned ds_roundup_to_prime (const unsigned bsize) {
#else
static inline unsigned ds_roundup_to_prime (const unsigned bsize) {
#endif
And in the header file I do
#ifdef DEBUG
unsigned ds_roundup_to_prime (const unsigned bsize);
#endif
Ideally source code shouldn't change to cater for unit tests. Unit-test framework, should must be capable of testing the source code as it will look in production.
Thanks
It's debatable whether or not static functions should be tested, as they aren't part of the public API.
I test static functions by including the unit-under-test, rather than linking against it:
foo.c (Unit under test)
static int foo(int x)
{
return x;
}
/* ... */
test_foo.c
#include "foo.c"
void test_foo(void)
{
assert( foo(42) == 42 );
}
int main(void)
{
test_foo();
}
Compile just that test:
$ gcc -Wall -Werror -o test_foo test_foo.c
$ ./test_foo
I test static functions in the following manner.
I have a header file called utility.h. It has the following definition:
#ifdef UNIT_TEST
#define UTILITY_STATIC(DECLARATION) extern DECLARATION; DECLARATION
#else
#define UTILITY_STATIC(DECLARATION) static DECLARATION
#endif
Every source file that has functions that are to be tested are declared as such:
#include "utility.h"
UTILITY_STATIC(void function(void));
UTILITY_STATIC(void function(void))
{
}
I have an additional header file (e.g. test_helper.h), used in the unit test executable, that has the line:
extern void function(void);
In this way, tests have access to function whereas source files that don't define UNIT_TEST do not.
Note
This can be used for static variables as well.

need a workaround for a "multiple definition" error

A toy code illustrating my problem is as follows:
stuff.h:
#ifndef STUFF
#define STUFF
int a;
int testarr[]={1,2,3};
#endif
fcn.h:
#include "stuff.h"
int b[]={5,6,7};
void fcn();
main.h:
#include "stuff.h"
#include <stdio.h>
fcn.c:
#include "main.h"
void fcn() {
printf("Hello\n");
}
main.c:
#include "main.h"
#include "fcn.h"
int main() {
fcn();
printf("HI\n");
}
An attempt to compile fails with:
/g/pe_19976/fcn_2.o:(.data+0x40): multiple definition of `testarr'
/g/pe_19976/main_1.o:(.data+0x40): first defined here
After doing some reading, I realize that defining the array testarr in the header file is a problem. But the thing is, in my real code, several files need access to testarr and it needs to have the same assigned values everywhere. I guess I could put it in main.h (?) but even if that would work, in my real code it logically belongs in stuff.h. How do I solve this conundrum?
BTW, based on something else I found, I tried defining testarr as extern but got the same problem.
When you put a variable definition into a header file, any .c file that includes it will have a copy of that variable. When you then attempt to link them, you get a multiple definition error.
Your header files should contain only a declaration of the variable. This is done using the extern keyword, and with no initializer.
Then in exactly one .c file, you put the definition along with an optional initializer.
For example:
main.c:
#include "main.h"
#include "fcn.h"
int a;
int testarr[]={1,2,3};
int main() {
fcn();
printf("HI\n");
}
stuff.h:
#ifndef STUFF
#define STUFF
extern int a;
extern int testarr[];
#endif
fcn.h:
#include "stuff.h"
extern int b[];
void fcn();
fcn.c:
#include "main.h"
int b[]={5,6,7};
void fcn() {
printf("Hello\n");
}
It is not clear why you are using so many global variables. The array
int testarr[]={1,2,3};
is defined as many times as there are compilation units (in your example there are at least two compilation units) that include the corresponding header.
Declare the array in a header like
extern int testarr[3];
and define it in a cpp module.
int testarr[]={1,2,3};
The same is valid for other global variables that have external linkage.
As for this remark
BTW, based on something else I found, I tried defining testarr as
extern but got the same problem.
Then the array with the specifier extern shall not be initialized in a header. Otherwise it is a definition of the array.

Using C Functions Defined in Shared Object Without Renaming Them

I have been reading the on-line book Basics of libuv and trying to rewrite them to work with both a static link and a dynamic link to the libuv library. I rewrote the watchers example (code below), but I had to "rename" the functions I retrieved from libuv.dylib to make it work, which means I had to write an entirely separate code path for the dynamic linking case. Can I somehow keep the same function names?
I want my code to look like this.
#include <stdio.h>
#include <uv.h>
#ifdef DYNAMIC
#include <dlfcn.h>
#endif
int64_t counter = 0;
void wait_for_a_while(uv_idle_t *handle, int status) {
counter++;
if (counter >= 10e6)
uv_idle_stop(handle); // This function pointer must be a global variable
}
int main(int argc, char **argv) {
uv_idle_t idler;
// Initialize code needed for dynamically-linked library
#ifdef DYNAMIC
void *lib_handle = dlopen("libuv.dylib", RTLD_LOCAL|RTLD_LAZY);
// Set up pointers to functions defined in libuv.dyld ...
#endif
uv_idle_init(uv_default_loop(), &idler);
uv_idle_start(&idler, wait_for_a_while);
printf("Idling...\n");
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
// Clean up dynamically linked code
#ifdef DYNAMIC
dlclose(lib_handle);
#endif
return 0;
}
Currently, it looks like this.
#include <stdio.h>
#include <uv.h>
#ifdef DYNAMIC
#include <dlfcn.h>
// Currently, I need to define function pointers with different names
// than the functions they call
uv_loop_t* (*uln)(void);
int (*ur)(uv_loop_t*, uv_run_mode);
uv_loop_t* (*udl)(void);
int (*uii)(uv_loop_t*, uv_idle_t*);
int (*uist)(uv_idle_t*, uv_idle_cb);
int (*uisp)(uv_idle_t*);
#endif
int64_t counter = 0;
void wait_for_a_while(uv_idle_t *handle, int status) {
counter++;
if (counter >= 10e6)
#ifdef DYNAMIC
uisp(handle);
#else
uv_idle_stop(handle); // This should be the only line remaining
#endif
}
int main(int argc, char **argv) {
uv_idle_t idler;
// Code path for dynamic linking case
#ifdef DYNAMIC
void *lib_handle = dlopen("libuv.dylib", RTLD_LOCAL|RTLD_LAZY);
// Retrieve symbol names from libuv.dylib
*(void **)(&uln) = dlsym(lib_handle, "uv_loop_new");
*(void **)(&ur) = dlsym(lib_handle, "uv_run");
*(void **)(&udl) = dlsym(lib_handle, "uv_default_loop");
*(void **)(&uii) = dlsym(lib_handle, "uv_idle_init");
*(void **)(&uist) = dlsym(lib_handle, "uv_idle_start");
*(void **)(&uisp) = dlsym(lib_handle, "uv_idle_stop");
uii(udl(), &idler);
uist(&idler, wait_for_a_while);
printf("Idling...\n");
ur(udl(), UV_RUN_DEFAULT);
dlclose(lib_handle);
// Code for static linking case
#else
uv_idle_init(uv_default_loop(), &idler);
uv_idle_start(&idler, wait_for_a_while);
printf("Idling...\n");
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
#endif
return 0;
}
Change:
#include <uv.h>
#ifdef DYNAMIC
#include <dlfcn.h>
/*...*/
into:
#ifndef DYNAMIC
#include <uv.h>
#else
#include <dlfcn.h>
/*...*/
Now, you can name your function pointer variables the same as the interfaces you want to call them as.
However, it is unclear why you need to do this at all. Normally, you just link your application with the dynamic library. You would only need to do what you are doing if you are experimentally changing the implementation of the dynamic library (treating it like a plugin).
In a comment, you mention that you need the definitions of structures in <uv.h>. Then to make my original proposal work, you would need to redefine those structures in the case of DYNAMIC, since you would not be using the header file. But, if the uv library ever changes, you would lose those changes and be forced to update your DYNAMIC version to match, which is an undesirable situation.
Another work around is to follow your original approach of defining different function pointer names, but then define macros to map the original function names to the function pointer names.
#include <uv.h>
#ifdef DYNAMIC
#include <dlfcn.h>
uv_loop_t* (*uln)(void);
int (*ur)(uv_loop_t*, uv_run_mode);
//...
#define uv_loop_new uln
#defin uv_run ur
//...
#endif

Can I re-define a function or check if it exists?

I have a question about (re-)defining functions. My goal is to have a script where I can choose to define a function or not.
Like this:
void func(){}
int main(){
if (func)func();
}
AND without the function, just:
int main(){
if (func)func();
}
Anybody an idea?
You can do this in GCC using its weak function attribute extension:
void func() __attribute__((weak)); // weak declaration must always be present
int main() {
if (func) func();
// ...
}
// optional definition:
void func() { ... }
This works even if func() is defined in another .c file or a library.
Something like this, I think. Haven't used function pointers much, so I may have gotten the syntax slightly wrong.
void func()
{
#define FUNC_PRESENT
// code
}
void (*funcptr)();
#ifdef FUNC_PRESENT
funcptr = func;
#else
funcptr = NULL;
#endif
int main()
{
if (funcptr)
funcptr();
}
Use function pointers, set them dynamically based on runtime conditions, and check for null pointers or wrap them in methods that do that check for you.
Only option in C I can think of.
In C++ you could combine templates and DLLs to dynamically define at runtime.
Really the only way that you can "choose to define a function or not" is with C preprocessor directives. For example:
#ifdef some_name
void func() {
do_whatever();
}
#else
//the else part is optional
#endif
To set these "variables" you use #define some_name
The trouble is, all of this needs to be done at compile time (before that, actually) so it can't be done with an if statement like in your example. If you want an if statement to control your program flow, just use it and don't bother with trying to rename functions or using function pointers or something.
Introduction
I guess that you are trying to do this:
Two modules, a.o and b.o
b.o contains a definition for void foo()
a.o calls void foo() only if b.o is also linked into the final executable.
This could be useful for a "plugin" system.
Variation 1
You can simulate it using function pointers. I don't know enough C to write this in proper C code, but pseudocode looks like this:
a.h
extern collectionOfFuncPtrs_t list;
int addFuncPtr();
a.c
#include "a.h"
collectionOfFuncPtrs_t list;
int addFuncPtr(FuncPtr p) {
- add func ptr to list
- return 0
}
int main() {
- loop through list of function pointers
- call functions through them
}
b.c
#include "a.h"
void bar() { /* ... */ }
static int dummy = addFuncPtr(&bar);
c.c
#include "a.h"
void ayb() { /* ... */ }
static int dummy = addFuncPtr(&ayb);
Conclusion
Now, you can link in b.o and/or c.o as you wish, and int main() will only call bar() and/or ayb() if they exist.
Variation 2
Experiment with variations on this theme if it looks like it may be useful to you. In particular, if you have only a specific number of conditionally-defined functions, you could use a bunch of individual function pointers rather than some list:
a.h
extern fptr_t bar_ptr, ayb_ptr;
a.c
#include "a.h"
int main() {
if (bar_ptr)
bar_ptr();
if (ayb_ptr)
ayb_ptr();
}
b.c
#include "a.h"
void bar() { /* ... */ }
fptr_t bar_ptr = &bar;
b_dummy.c
#include "a.h"
fptr_t bar_ptr = 0;
c.c
#include "a.h"
void ayb() { /* ... */ }
fptr_t ayb_ptr = &ayb;
c_dummy.c
#include "a.h"
fptr_t ayb_ptr = 0;
Conclusion
Now either link b.o or b_dummy.o; and either link c.o or c_dummy.o.
I hope you get the general idea, anyway...!
Bootnote
This is a lot easier in C++ where you can write a module registration system very easily with std::maps and constructors.
In C? Only by using the preprocessor as stated in other answers.
C isn't a dynamic language like, say, Python.
The right way to do what I think you're asking about in C is to use function pointers. You can take the address of a function, assign it to a variable, test it for nil, etc. However, plain old C isn't a very dynamic language; you might be better off using a different language.
if you don't mind compiler specific extension, you can use __if_exists:
#include <iostream>
using namespace std;
// uncomment the following, and it'll still work
void maybeFunc(){ cout << "running maybe" << endl; }
int main(){
cout << "hi!" << endl;
__if_exists(maybeFunc)
cout << "maybe exists!" << endl;
maybeFunc();
}
}
this works in msvc by default, and in clang if you use the -fms-extensions flag.

Resources