best practice to access data - c

I have a function in source file 1 :
Source file 1:
function in Source file 1.
Code:
char day[7];
f1:
{
....
....
....
after some work fill the
day[0]= random number;
.
.
.
.
day[6]=random number;
}
Quote:
Source file 2:
f2:
{
extern dayval[];
//do stuff
}
And now i want to access those day[7] values from array in source file 2.
If i declare array as extern in source file 2 immediately after f1 in source file is executed will the values remain same or will it be zero
Well forgive my stupidity i have started learning C language just now and it's been Quite a hell of ride Smile.
I hope you guys will enlighten me with your suggestions
Which is the best way to access data.I'm working on embedded systems and some say pass by reference is a good option.I would be delighted to have your views on it.
Regards

Yes, it can be solved by declaring it as an extern variable, but it needs to be global in source1.c too. Local variables cannot be accessed from outside their scopes, at least not by name.
So, in source1.c:
char day[7];
void function1(void)
{
day[0] = ...;
/* and so on */
}
then in source2.c:
extern char day[7];
void function2(void)
{
printf("oh, source1 has set day[0] to %c\n", day[0]);
}
of course, you must make sure that function1() from source1.c runs before function2() from source2.c, in order to initialize the array.
You could have a separate main.c that does:
int main(void)
{
function1();
function2();
return 0;
}
Then compile them all together, using something like this (assuming gcc in a Unix-type environment):
$ gcc -o myprogram main.c source1.c source2.c

Related

Where are variables stored when you have "global" variables in multiple C files?

When you have multiple C files, say main.c and process.c I was trying to understand where variables declared outside of functions in both cases are stored.
// this is main.c
#include <stdio.h>
#include "process.h"
int foo = 1;
void main() {
int count = get_counter();
}
// this is process.c
#include <stdio.h>
int counter = 0;
int get_counter() {
return counter;
{
So when you have two c files, your main.c and a process.c, you can call get_counter() in main.c and it will return the value from the process.c file. What I was trying to understand is where the compiler, or how it stores int foo in main.c and int count in process.c? Is this part of some data storage section? It is not on the stack right? It also seems having a separate process.c file makes it so it is not a global variable.
I have been really trying to understand how variables scope is handled and can get a little tricky for me. Does the #include "process.h" essentially compile as if you had the functions and their prototypes in the main.c above the rest of the code? To me that would make the int counter global so I know I am confusing something.
Thank you for taking your time to read this.
That's a function of the executable file format, not the C language itself. For ELF (*nix and similar systems) and PE/COFF (Windows and similar), globals or other objects with static storage duration will be stored in either the .bss or .data sections depending on whether they're initialized or not. This is space allocated from within the program's binary image itself (not taken from the stack or heap).
Other executable file formats may use different section names.

Extern Variables seemingly not working "symbols not found for architecture x86_64"

I've been searching through Stackoverflow and the web for the answer and it seems like I'm doing this correctly, however I can't get it to work.
I made a test program for using extern, (it's on xCode using the projects feature if that makes a difference). I'm trying to declare a variable, that I can access anywhere in my program, whenever I change the value of that variable, I want to be able to access the changed value.
What I've done so far is I have a header file
externFile.h
and a
externFile.c
and of course my
main.c
In externFile.h I defined:
extern int ply;
In main.c I have:
int main()
{
int ply;
ply = 5;
printPly();
}
In externFile.c I have:
void printPly(){
printf("%d is ply.\n", ply);
}
However I'm getting this error:
_ply referenced from _printPly
ld symbols not found for architecture x86_64
Does anyone have any sort of ideas about this?
You haven't actually defined ply globally:
int main(void)
{
int ply;
ply = 5;
printPly();
}
Here, ply is a local variable, not a global, since it is defined inside of a function. The extern line in your header file does not define the global, but declares it. It says "this variable exists somewhere", but it doesn't create it. Because there is no global defined, you get an undefined reference error.
Global variables must be defined at file scope, i.e. outside of a function:
int ply = 5;
int main(void)
{
printPly();
}

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.)

how to update extern variable in C

I have these files
test1.h
extern int value;
void inc_value();
int print_value();
test1.c
#include "test1.h"
int value=0;
void inc_value()
{
printf("inc value from test3.c = %d\n", value++);
}
int print_value()
{
printf(" value in test1.c = %d\n", value);
return value;
}
test3.c
# include "test1.h"
main()
{
inc_value();
}
test4.c
# include <stdio.h>
#include "test1.h"
main()
{
printf("value from test4 = %d\n", print_value());
}
I'm updating variable "value" from test3.c and trying to read it from test4.c. However test3.c is unable to update the "value" that is declared in test1.h and defined in test1.c
What point am I missing here..
This will never work.
You can't use an external variable from two different programs and magically expect it to work. It's just ... wrong. Each program runs in its own address space, and doesn't know anything about any other process' address spaces. There are techniques for doing this (look up interprocess communucation), but that's a whole different area.
The way extern works is that it allows you to access a variable defined in a different C file within the same program.
You seem to be mis-understanding at a quite fundamental level how the programs you are writing work and execute, since you expect this to work. I recommend reading up more on how C works, and also perhaps a bit on how operating systems host programs in order to run them.
One way of sharing information between programs like you describe is to store the data in a file, which is written by one program (the one that runs first) and read by the other, but that is quite tricky to get right, too.
If you want to call void inc_value() from another file, you should declare it (probably in the header):
void inc_value();
If you want to directly access value, you can, as it was declared as an extern:
# include "test1.h"
main()
{
value = 6;
}
Also note, that in current implementation of inc_value, the value will be incremented after it is passed to printf, e.g. the printed value will be the previous one.
You should put extern int value in the test3.c and just put int value in test1.h.Look at this link: http://www.learncpp.com/cpp-tutorial/42-global-variables/ Hope this helps...

How to run constructor even if "-nostdlib" option is defined

I have a dynamic library that contains a constructor.
__attribute__ ((constructor))
void construct() {
// This is initialization code
}
The library is compiled with -nostdlib option and I cannot change that. As a result there are no .ctor and .dtor sections in library and the constructor is not running on the library load.
As written there there should be special measures that allow running the constructor even in this case. Could you please advice me what and how that can be done?
Why do you need constructors? Most programmers I work with, myself included, refuse to use libraries with global constructors because all too often they introduce bugs by messing up the program's initial state when main is entered. One concrete example I can think of is OpenAL, which broke programs when it was merely linked, even if it was never called. I was not the one on the project who dealt with this bug, but if I'm not mistaken it had something to do with mucking with ALSA and breaking the main program's use of ALSA later.
If your library has nontrivial global state, instead see if you can simply use global structs and initializers. You might need to add flags with some pointers to indicate whether they point to allocated memory or static memory, though. Another method is to defer initialization to the first call, but this can have thread-safety issues unless you use pthread_once or similar.
Hmm missed the part that there where no .ctor and .dtor sections... forget about this.
#include <stdio.h>
#include <stdint.h>
typedef void (*func)(void);
__attribute__((constructor))
void func1(void) {
printf("func1\n");
}
__attribute__((constructor))
void func2(void) {
printf("func2\n");
}
extern func* __init_array_start;
int main(int argc, char **argv)
{
func *funcarr = (func*)&__init_array_start;
func f;
int idx;
printf("start %p\n", *funcarr);
// iterate over the array
for (idx = 0; ; ++idx) {
f = funcarr[idx];
// skip the end of array marker (0xFFFFFFFF) on 64 bit it's twice as long ;)
if (f == (void*)~0)
continue;
// till f is NULL which indicates the start of the array
if (f == NULL)
break;
printf("constructor %p\n", *f);
f();
}
return 0;
}
Which gives:
Compilation started at Fri Mar 9 09:28:29
make test && ./test
cc test.c -o test
func2
func1
start 0xffffffff
constructor 0x80483f4
func1
constructor 0x8048408
func2
Probably you need to swap the continue and break if you are running on an Big Endian system but i'm not entirely sure.
But just like R.. stated using static constructors in libraries is not so nice to the developers using your library :p
On some platforms, .init_array/.fini_array sections are generated to include all global constructors/destructors. You may use that.

Resources