In a source file inv_mpu.c there is a structure definition gyro_state_s and a file scope variable declaration:
static struct gyro_state_s st = {
.reg = ®,
.hw = &hw,
.test = &test
};
Nested in this structure is a member st.chip_cfg.bypass_mode that I wish to access from withing another file.
Question: How to read the state of this flag st.chip_cfg.bypass_mode within another file?
I have tried extern struct gyro_State_s st ;, but this remains unrecognized when I test it in if(!st.chip_cfg.bypass_mode).
Attempting to expose all of st and its definition just to access this one flag is a bad design and should be avoided. Globals are always bad, and in this case you would be unnecessarily making all the internals of st visible to the entire program.
inv_mpu.c already has a function mpu_set_bypass() which is called before it is used, so must have a prototype somewhere, most likely in the existing header inv_mpu.h. The simplest, safest and most in-keeping with the existing code style solution would be to add a "getter" accessor counter-part mpu_get_bypass().
In inv_mpu.c you might add:
unsigned char mpu_get_bypass( void )
{
return st.chip_cfg.bypass_mode ;
}
The add the prototype declaration to inv_mpu.h thus:
unsigned char mpu_get_bypass( void ) ;
Then in the accessing source file, you #include "inv_mpu.h", then call the getter, thus for example:
if( !mpu_get_bypass() ) ...
Put the structure in a shared header that is included in both files.
extern means: 'this is defined/instantiated elsewhere'
Since a structure on it's down doesn't compile to any physical code (an instance of a structure does, the structure itself just describes how to create an instance of it) you just need to define the same structure in both files, this is best done by putting the structure in a shared header then including the header in both of the files you need the structure in.
Related
In C, you can use the static keyword to make global variables and functions private to the file in which they're defined. The compiler won't export these symbols, and thus the linker will not allow other modules to use these definitions.
However, I'm struggling to figure out how to restrict a struct definition such that it doesn't get added as an exported symbol that could accidentally be used by another module during the linking process. I would like to restrict this to the only file in which its defined.
Here are my attempts thus far which I've been struggling with.
// structure that is visible to other modules
struct PrivateStruct
{
int hello;
int there;
};
// this seems to throw an error
static struct PrivateStruct
{
int hello;
int there;
};
// i would ideally like to also wrap in the struct in a typedef, but this definitely doesn't work.
typedef static struct PrivateStruct
{
int hello;
int there;
} PrivateStruct;
Edit: I realize if I just define this struct in the .c file, others won't know about it. But won't it still technically be an exported symbol by the compiler? It would be nice to prevent this behavior.
I realize if I just define this struct in the .c file, others won't know about it. But won't it still technically be an exported symbol by the compiler?
No. Whether you are talking about structure tags or typedefed identifiers, these have no linkage. Always. There is no sense in which it would be reasonable to say that they are exported symbols.
This is among the reasons that header files are used in C. If you want to use a structure type in one compilation unit that is compatible with a structure type in a different compilation unit then compatible structure type declarations must appear in both. Putting the definition in a header makes it pretty easy to achieve that.
yes..... you can use pointers to the structure, and to the outer world it is not deferrable. Normally, that requires two header files, the first is the public one:
header mystruct.h
This header is public, used by client code.
struct my_opaque;
/* we cannot use *p fields below, as the struct my_opaque is
* incompletely defined here. */
void function_using(struct my_opaque *p, ...);
header mystructP.h
This header is private, and includes the public header file to maintain the
API to the client code.
#include "mystruct.h" /* safety include (1) */
struct my_opaque {
/* ... */
};
implementation mystruct.c
In implementation code, we include the private header file, and so, we have full access to the structure fields.
#include "mystructP.h"
/* we have full definition, as we included mystructP.h */
void function_using(struct my_opaque *p,
...)
{
... /* we can use p->fields here */
}
(1) the safety #include allows to change the struct my_opaque and the API functions, and the compiler to blame you if you change something in the api to the caller modules, forcing you to recompile if you change something in that API.
Not particularly experienced in C, chance made be responsible for a small microcontroller project.
So, i have a structure which resides on a file1.c. Its used by several functions in that file. It was defined as static volatile Structure struct right now.
The struct is declared static because i read on a book called "embedded system development coding reference guide" that "variables accessed by several functions defined in the same file shall be declared with static in the file scope". Well, its used by several functions, and i want it file based so i thought it matches that description. Volatile because it holds some AD reads from some ports.
I also have a file2.c which needs to access values of the same structure.
From my understanding my options are the following
on file1.h define that structure as extern and access
#include file1.h on file2.c and access it.
From my undestanding though,this will make the structure visible to
the whole file2.c even though only 1 function there is going to need
it
keep the structure as is, and make a function in file.2 which accepts
the structure by reference function(Structure *struct), make that
function accessible from file1.c and just pass the value by ref
function(&struct)
Which one is the best approach? I know that both of them work, but is there a specific reason why i should use one and not the other etc?
I want to clarify that the typedef { variables } Structure, is in another header file which is included on both file1.c and file and file2.c, so there is no question about the files recognizing the structure. I am asking which is the best way to access that structure from where is needed.
You need to move the struct definition to an header file otherwise file2.c won’t recognize the struct even you pass it by reference . A reference or a pointer still need a class/struct definition to be compiled...
Based on your clarification, the struct should probably not be volatile qualified. Just because the actual ADC hardware registers are volatile, it doesn't mean that the data read from them has to be. Except if you fill the struct from an ISR or from DMA, but that doesn't sem to be the case(?).
The proper design is then to place the typedef of the struct in the header file and the variable definition in the .c file. Then provide access to the variable through getter/setter functions. However, consider if other code really need to access the struct as is, or if they just need a few values from it. Overall, use private encapsulation and stay away from extern.
Is it possible to declare a structure type that is only visible in the .c file which uses the structure? I know that by putting static in front of a external data object, you change the linkage of the variable to be internal. But is it possible to put static in front of the declaration of a new struct type, like the following?
static struct log{
...;
...;
};
typedef struct log log;
If it is not possible to make the structure type, say log as above, to be "private", does it mean that even though other source files do not know the existence of the name (which is log in my example) of the structure, accidental name collisions can still happen if they name some variables log (assuming I will link all object files) ?
EDIT: I am not familiar with how compiler/linker works. If there is a global variable name log, and the file that contains the global variable is linked to the sole source file in which structure log is defined, wouldn't that cause any confusion when linking, one log is a variable name while another log is a type name?
No. The only way to make a struct private is to only have its definition available in the files that use it -- don't put it in a common header file. If it's only used in one source file, then just define it in that source file, but if it's used in more than one source file, you have a tricky problem: you can define it in each source file, but that's fragile since you have to remember to change each instance of it when you make any changes; or, you can define it in a private header file, and make sure only those source files include the private header.
Name collisions in different source files are ok, as long as they don't try to interface with each other in any way. If you have a struct log defined in one file and a different definition of struct log in a different file, do not ever pass one log to the other. In C, the structure name doesn't become part of any symbol names in the object file -- in particular, there's no name mangling of function names to include the parameter types (like C++ does), since function overloading is illegal in C.
No. static is a storage type; it is not meaningful to apply it to a type outside a variable declaration.
If you don't want to define struct log in your header file, you don't have to. Simply writing the typedef as:
typedef struct log log;
is sufficient, so long as you only deal with log * pointers. However, you will need a full definition of the structure to declare a log (or take sizeof(log)), because the size of the structure depends on what it contains.
With regard to name collisions, keep in mind that structures and types are not managed by the linker. The linker only cares about globally visible symbols, such as functions and variables. That being said, you should probably apply a prefix to your type names (e.g, mylib_log_t) to avoid confusion, particularly because log is a math function in the standard library.
You have a reason to write this:
static int a;
Because it prevents the linker from combining it with a defined somewhere else.
The linker has nothing to do with structs, so there is no worries putting in different c files.
As long as its in different c files, there will be no name confusions.
This isn't possible in general. But I can think of a hack that might work on some compilers.
The reason why this is hard to do is because the C compiler needs to know what the structure looks like in order to generate calls to functions with instances of the structure as argument.
So, suppose that you define a library with the following header:
struct foo {
int32_t a, b;
};
foo make_foo(int arg);
foo do_something(foo p1, foo p2);
Then to compile a program which makes a call to do_something, your compiler usually needs to know what the structure foo is like, so that it can pass it as an argument. The compiler can do all sorts of weird things here, like passing part of the structure via registers and part via the stack, so it really needs to know what the structure looks like.
However, I believe that in some compilers, it is possible to give the indication that the structure should be passed entirely via the stack. For instance, the regparm(0) function attribute should work for GCC if you have i386 as your target architecture (docs).
In that situation, it should be possible to do something like this: create a 'public version' of the header file, and in that file, instead of laying out the full struct, you create an undiferentiated version of it:
struct foo {
uint8_t contents[SIZE_OF_STRUCT_FOO];
}
where SIZE_OF_STRUCT_FOO is whatever sizeof(struct foo) returns when you define the struct in the usual way. You are then basically saying that "foo" is a struct with SIZE_OF_STRUCT_FOO bytes. Then, as long as the calling convention treats these two structs in the same way, it should work.
I develop an embedded application which uses the MindTree Bluetooth SDK.
I have the following in a header file:
typedef struct {
UCHAR outputDir;
UCHAR reset;
UCHAR nack;
UCHAR startCondition;
UCHAR stopCondition;
UCHAR busy;
} USCI_ConfigurationFlags;
static USCI_ConfigurationFlags usciConfigFlags = { UCTR, UCSWRST, UCNACKIFG, UCTXSTT, UCTXSTP, UCBBUSY };
Later in two .c files I include the above header and use the usciConfigFlags on different occasions sometimes from within an interrupt.
Is this legal?
I'm trying to understand why(and if it is related to the question) the values of the struct change at runtime, after calling the BT_bluetooth_on method in the SDK.
Thanks,
Adam.
static here doesn't mean what you think it means. It means that the declaration and variable will only be visible in one compilation unit. That is, you have two independent instances of usciConfigFlags.
If you want a global variable, you need to use extern not static and make the actual declaration (without extern) with the initial value in one of your c files.
Also be weary of changing the values in the struct without proper locking. Read-only concurrent access is usually fine.
There is no problem you include the header in two .c file. The static modifier limits the accessible scope of the variable in the file including the header only. The two usciConfigFlags in two different files are not identical.
Also static does not mean constant. So you can modify the value of the structure in whatever way you want.
The following is from wikipedia
In computer programming, a static variable is a variable that has been
allocated statically — whose lifetime extends across the entire run of
the program. This is in contrast to the more ephemeral automatic
variables (local variables), whose storage is allocated and
deallocated on the call stack; and in contrast to objects whose
storage is dynamically allocated.
Prepending a static keyword to a variable makes it visible only in the current translation unit (i.e. if within a function, only that function and if within a file, only that file).
It is never a good idea to define a variable in a header file. Even if you need two static variables in two different files with the same name, it is better that you put in the .c file itself as it helps in better maintaince and readability as you will be clear in which all files it is actually present and is being used.
If you add it in a header file, then at a later point, if some other .c file includes this header, then unneccessarily this variable will included for that translation unit.
Epsalon had suggested other good points which you can consider.
Is there any way to keep global variables visible only from inside a library while inaccessible from programs that access that library in C?
It's not that it is vital to keep the variable protected, but I would rather it if programs couldn't import it as it is nothing of their business.
I don't care about solutions involving macros.
If you use g++, you can use the linker facilities for that using attributes.
__attribute__((visibility("hidden"))) int whatever;
You can also mark everything as hidden and mark explicitly what is visible with this flag: -fvisibility=hidden
And then mark the visible variables with:
__attribute__((visibility("default"))) int whatever;
static int somelocalvar = 0;
that makes somelocalvar visible only from whithin the source file where it is declared (reference and example).
Inside the library implementation, declare your variables like that:
struct my_lib_variables
{
int var1;
char var2;
};
Now in the header for end-users, declare it like that:
struct my_lib_variables;
It declares the structure as an incomplete type. People who will use the header will be able to create a pointer to the struct, but that's all. The goal is that they have to write something like that:
#include "my_lib.h"
struct my_lib_variables* p = my_lib_init();
my_lib_do_something(p);
my_lib_destroy(p);
The libray code is able to modify the variables, but the library can't do it directly.
Or you can use global variables, but put the extern declarations inside a header which will not be used by the end-user.
You can use another header file for exporting functionality to outside modules than you have for the internal functionality and thus you don't have to declare globals that doesn't have to be accessible from outside the module.
Edit:
There is only linker problems if you declare things more than once. There is no need to keep all global data in one header file, in fact, there may be a wise reason top split it up into several smaller pieces for maintainability and different areas of responisiblity. Splitting up into header files for external data and internal data is one such reason and this should not be a problem since it is possible to include more than one header file into the same source file. And don't forget the guards in the header files, this way, collision in linking is mostly avoided.
#ifndef XXX_HEADER_FILE
#define XXX_HEADER_FILE
code
#endif