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
Related
I have two cross cutting concerns in my design of my software. The memory allocator tracks memory usage in its struct(class) member variables. I also have a logger. Right now I am passing the logger and the allocator into the constructor of my objects. I can maintain a reference to them but then I would have to do that in every struct(class) I create. It would be nice if they were global but I am not sure how to do that in C. Can I construct a global memory allocator that will correctly keep track of bytes used without passing it in to my functions calls to reference?
EDIT:
I am trying to use object_tracker as a global variable in my create and destroy functions. When I compile and test the files below this is the result I get: How do I use extern correctly to get the global reference to work?
gcc -I ../include object_tracker.c test_file.c test_main.c -o test
./test
/tmp/ccuT8Z1A.o: In function `Test_Create':
test_file.c:(.text+0xb): undefined reference to `object_tracker'
/tmp/ccuT8Z1A.o: In function `Test_Destroy':
test_file.c:(.text+0x4b): undefined reference to `object_tracker'
collect2: error: ld returned 1 exit status
test_file.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "object_tracker.h"
#include "test_file.h"
struct Test* Test_Create() {
struct Test* test = (struct Test*)Object_Tracker_Obj_Alloc(object_tracker, 1, sizeof(struct Test));
test->foobar = 10;
return test;
}
void Test_Destroy(struct Test* test) {
if(test != NULL) {
Object_Tracker_Obj_Free(object_tracker, test);
}
}
test_file.h
#ifndef _TEST_FILE_H_
#define _TEST_FILE_H_
#include "object_tracker.h"
extern struct Object_Tracker* object_tracker;
struct Test {
int foobar;
};
struct Test* Test_Create();
void Test_Destroy(struct Test* test);
#endif
test_main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "object_tracker.h"
#include "test_file.h"
int main(int argc, char* argv[]) {
struct Object_Tracker* object_tracker = Object_Tracker_Create();
struct Test* test = Test_Create();
Test_Destroy(test);
printf("heello\n");
}
Yes you can do that in C, just define the global memory allocator at the top of the file, and everything below it will know its existence.
In order for other files to have an eye on it, use extern, as explained in How do I share a global variable between c files?
Keep in mind though that global variables should be avoided when possible.
I removed the extern keyword and made a globals.h file with the declaration for object_tracker. I included it every "class" file and it works. I am still not sure what the extern keyword is used for.
According to your example there is no variable ‘object_tracker’ defined globally. You have define such variable, but it is inside main function.
struct Object_Tracker* object_tracker = Object_Tracker_Create();//Inside main function ???
Since it is defined inside main function is it not visible to other functions.
So move this definition to global scope. The updated test_main.c is as below.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "object_tracker.h"
#include "test_file.h"
struct Object_Tracker* object_tracker; //Global scope variable
int main(int argc, char* argv[]) {
object_tracker = Object_Tracker_Create(); //Assign value for the variable
struct Test* test = Test_Create();
Test_Destroy(test);
printf("heello\n");
}
I want to call function according to func_name string.
My code is here below:
#define MAKE_FUNCNAME func_name##hello
void call_func(void* (*func)(void))
{
func();
}
void *print_hello(void)
{
printf("print_hello called\n");
}
int main(void)
{
char func_name[30] = "print_";
call_func(MAKE_FUNCNAME);
return 0;
}
But this code doesn't work. I want code to work like call_func(print_hello). But preprocessor treated my code like call_func("print_hello"). How to use macro in C to make my exception? Or is it not possible using C?
Then problem with your code is that the value of func_name is only known at run-time.
You can however to it like this:
#define MAKE_FUNCNAME(FUNCNAME) FUNCNAME##hello
void call_func(void* (*func)(void))
{
func();
}
void *print_hello(void)
{
printf("print_hello called\n");
}
int main(void)
{
call_func(MAKE_FUNCNAME(print_));
return 0;
}
But it is not possible to use a string value within macro parameters like in your code snippet.
If you want to get call functions with their names using string values you can use a table to store function pointer with function names like this:
struct {
const char *name;
void (*ptr)(void);
};
You can use an array of this structure to find out the function pointer at run-time using a string value. This is the most common solution to using run-time strings to call functions using their names.
You can't do that. The value of func_name is known at run-time (even though it is a const char *), while you want to determine what to call at precompile-time. You should turn your cpp macro into something different (such as an if/switch statement or using an indirection).
Maybe you could have a look to dlsym().
Not sure I really understand the question, but if you want to "build" the function name at runtime and then call the corresponding function, it should be possible with dlsym()
/* compile with: gcc example.c -ldl -rdynamic */
#include <dlfcn.h>
#include <stdio.h>
int print_hello(void)
{
return printf("hello\n");
}
int main(int argc, char *argv[])
{
const char *name = "print_hello";
if (argc == 42)
print_hello(); /* for compiler not to remove print_hello at
* compile time optimisation in this example*/
void *handle = dlopen(NULL /* self */, RTLD_NOW);
int (*f)(void) = dlsym(handle, name);
f();
return dlclose(handle);
}
I have created a small program mirroring my source code. Here main, when in debug mode, calls external library tester functions before it runs the main app. Imagine the constructor function in that library allocates memory and when in debug also tests some static functions. If that library is tested, it runs static tester code. If that library is used, static tester code. the static testers run every time the library function is called.
main.c
// calls test and library
#include <stdio.h>
#include <stdlib.h>
// to test if the lib is there and the function does what it says claims
extern int testExternalLibFunctions(void);
#include "lib.h"
int main(){
testExternalLibFunctions();
printf("main function uses doTheTango\n");
doTheTango();
// do the magic stuff here and
doTheTango();
return 0;
}
test_lib.c
#include <stdio.h>
#include "lib.h"
static int Static_doTheTangoTest();
int testExternalLibFunctions(){
// define DO_THE_TANGO_TEST_SELF_TRUE
Static_doTheTangoTest();
// undefine DO_THE_TANGO_TEST_SELF_TRUE
return 0;
}
int Static_doTheTangoTest(){
printf("external function tester calls doTheTango\n");
doTheTango();
return 0;
}
lib.h
#ifndef DO_THE_TANGO_HEADER
#define DO_THE_TANGO_HEADER
extern int doTheTango();
#endif // DO_THE_TANGO_HEADER
lib.c
#include <stdio.h>
#include <assert.h>
#include "lib.h" //self
// ONLY HERE SHOULD STATIC FUNCTIONS BE TESTED
static int STATIC_TEST();
int doTheTango(){
printf("Dancing is fun - ");
// if defined DO_THE_TANGO_TEST_SELF_TRUE
STATIC_TEST();
// endif
getchar();
return 0;
}
int STATIC_TEST(){
printf("Static test 1, Yet again!");
return 0;
}
It is not the intention to split tester and main function, because the main is calling more testers, etc ... they are inter-dependant!
How can I make the library do the static tests only when first included? Something like in python, where you test
if(__name__ == __main__) -> do the static tests
I'm not sure I understand what you are trying to do. I see from the source code that you say "Static test 1, Yet again!", so I assume you don't want the STATIC_TEST to be called on subsequent calls to doTheTango.
If this is what you want, then do:
int doTheTango(){
static int isTested = 0;
printf("Dancing is fun - ");
if (!isTested) {
isTested = 1;
STATIC_TEST();
}
getchar();
return 0;
}
This is working! and actually also what I was looking for!
// in the global doTheTangoTest you define:
extern int TEST_TANGO_SELF;
doTheTangoTest{
// to set it to 1 if the library is testing itself
TEST_TANGO_SELF = 1;
doTheTango();
// to set it to 0 if testing itself is finished
TEST_TANGO_SELF = 0;
}
and in doTheTango source
// you define again, but not as extern this time, just as int
int TEST_TANGO_SELF;
int doTheTango(){
printf("Dancing is fun - ");
// and use this global variable in a simple if statement
if(TEST_TANGO_SELF){
STATIC_TEST();
}
getchar();
return 0;
}
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;
}
Lets say I have a main.c file
#include "library.h"
#define LIBRARY_VALUE 5
int main(void)
{
somefunction1();
return 0;
}
library.h
void somefunction1(void);
library.c
#include "library.h"
#ifndef LIBRARY_VALUE
#define LIBRARY_VALUE 1
#endif
static unsigned char oneString[LIBRARY_VALUE]; // Also I need to be able
// to use the value to initialize
// static arrays that will be
// modified by somefunction1();
void somefunction1(void)
{
printf("The Library Value is %d\n", LIBRARY_VALUE);
}
What I want to do here, is to be able to compile main.c and having LIBRARY_VALUE‘s value to be used as I defined right after the include in main.c.
How should I use GCC in order to achieve this?
I do need the value to be defined in main.c.
In case I have to change my code, I need a minimum working example code please. So I know clearly how to do this. Thanks.
In C there is no way for different .c files to share a common macro defined in one of the .c files. The tradition is to put it in a .h file, but you say this will not work for you.
You will need a type of "constructor" function that sets up your "static" information at run time. This constructor can be called directly by main.c, or indirectly by having main.c define an extern the library picks up.
I'll throw you some code, but I haven't tried to compile it... I'll leave that as an exercise for the student.
main.c
#include "library.h"
int const library_value = 5;
int main(void)
{
somefunction1();
return 0;
}
library.h
extern int const library_value;
void somefunction1(void);
library.c
#include <assert.h>
#include "library.h"
static unsigned char *oneString;
// destroy any memory from lib_init().
static void lib_clear(void)
{
if ( oneString )
{
free(oneString);
oneString = NULL;
}
}
// initialization - strop the static if the caller is to start it up.
static void lib_init( void )
{
if ( ! oneString ) // (defensive "if" to be sure)
{
assert( library_value > 0 );
oneString = (unsigned char*)malloc( library_value );
atexit( &lib_clear );
}
}
void somefunction1(void)
{
if ( ! oneString ) // if the main() is not calling an the constructor then
lib_init(); // // every method within the library must do so.
printf("The Library Value is %d\n", library_value);
}
The lib_init() and lib_clear() methods could be made externs with a lib_init( int size ) signature to take the size.
Your goal seems to have a single definition referenced multiple places.
There are a limited number of possibilities:
#define in .h
extern defined in main, or somewhere else outside of library.
extern defined in library.
Value passed by caller to library, perhaps an initialization call for the library.
Something defined before #include library.h that is picked up by library.h. I don't like this one.
As alfa says, make it a compile-time definition.
An example of a #define within library.h.
// library.h
#ifndef LIBRARY_VALUE
#define LIBRARY_VALUE 1
void somefunction1(void);
#endif
Or, have main define a value defined by the caller and referenced by the library:
// library.h
extern int const library_value; // caller to define in main
void somefunction1(void); // function for caller
// main.c
int const library_value = 5;
int main(void)
{
somefunction1();
return 0;
}
The one I don't like is:
//main.c
#define LIBRARY_VALUE 5
#include "library.h"
//library.h
#ifdef LIBRARY_VALUE
int const library_value = LIBRARY_VALUE; // executable code in .h files is evil
#endif
Some of the reasons I dont' like this is that it is obscure and unconventional, if two or more callers of library.h define LIBRARY_VALUE you will, or at least should, get obscure link time errors. The same applies if LIBRARY_VALUE is not defined by an #include... library.c itself can not define a default value. No, I'd much rather call an initialization function for the library that accepts the constant.
The problem with the way you seem to want this to work, is that the constant gets used when the library is compiled -- you can't use one value when compiling the library and then compile a program with a different value and expect the library's code to magically change to use the new constant. You have some options when it comes to alternatives, though.
You could move the array into the program rather than the library, and give the library a pointer to it, and its size.
Or you could use a dynamically allocated array in the library, and add an initialization function to do the allocation (using the size provided by the program).
Or, you could ditch the library and just compile its code as part of the program -- then you can use a constant defined for the program as long as its done where the (previously) library code will see it.
Recommendation (assuming you want "myarray" visible outside the library):
// library.h
#ifndef LIBRARY_H
#define LIBRARY_Y
#define ARRAY_SIZE 5
extern unsigned char myarray[ARRAY_SIZE]; // Also I need to be able
// to use the value to initialize
// static arrays that will be
// modified by somefunction1();
void somefunction1(void); // function for caller
#endif
/* LIBRARY_H */
Otherwise, if you just want "somefunction1()" and the array size, then declare another function, "array_size ()":
// library.h
#ifndef LIBRARY_H
#define LIBRARY_Y
#define ARRAY_SIZE 5
int array_size (); // library.c will define "myarray" and it will
// define function array_size as "return ARRAY_SIZE;"
void somefunction1(void); // function for caller
#endif
/* LIBRARY_H */
ALSO:
Please remember that "static" has two meanings:
1) Hides visibility of a variable or function name to file scope (the name is "invisible" outside of the source file)
2) allocates space for the object from static storage (instead of the heap (malloc/new) or stack (local variables)).
If you only want the "static storage" part; then you don't need the keyword "static". Just define your variable outside of a function, and you're set :).
Yet another issue is whether you want to make "ARRAY_SIZE" a compile time variable. If so, you should make sure it gets defined EXACTLY ONCE (when library.c is compiled), and is used IN ONLY ONE PLACE (library.c and library.c only). For example:
// library.c
#include "library.h"
#ifndef ARRAY_SIZE
#error ARRAY_SIZE IS UNDEFINED!
#else
static unsigned char myarray[ARRAY_SIZE];
int array_size ()
{
return ARRAY_SIZE;
}
#endif
...
What you are trying to do is not possible because library.c and main.c are compiled separately. You should compile library.c with "gcc -DLIBRARY_VALUE=5 ..." instead.