File api.h
#include <stdio.h>
#ifndef API
#define API
struct trytag;
typedef struct trytag try;
void trial (try *);
#endif
File core.h
#ifndef CORE
#define CORE
struct trytag
{
int a;
int b;
};
#endif
File func.c
#include "api.h"
#include "core.h"
void trial (try *tryvar)
{
tryvar->a = 1;
tryvar->b = 2;
}
File main.c
#include "api.h"
int main ()
{
try s_tryvar;
trial(&s_tryvar);
printf("a = %d\nb = %d\n", s_tryvar.a, s_tryvar.b);
}
When I compile, I get:
main.c:5: error: storage size of ‘s_tryvar’ isn’t known
If I include core.h in main.c this error doesn't come as try is defined in core.h. But I want the structure try to be hidden to main.c — it should not know the members of try structure. What am I missing?
I don't think what you're trying to do is possible. The compiler needs to know how big a try structure is to compile main.c. If you really want it to be opaque, make a generic pointer type, and instead of declaring the variable directly in main(), make alloc_try() and free_try() functions to handle the creation and deletion.
Something like this:
api.h:
#ifndef API
#define API
struct trytag;
typedef struct trytag try;
try *alloc_try(void);
void free_try(try *);
int try_a(try *);
int try_b(try *);
void trial (try *);
#endif
core.h:
#ifndef CORE
#define CORE
struct trytag
{
int a;
int b;
};
#endif
func.c:
#include "api.h"
#include "core.h"
#include <stdlib.h>
try *alloc_try(void)
{
return malloc(sizeof(struct trytag));
}
void free_try(try *t)
{
free(t);
}
int try_a(try *t)
{
return t->a;
}
int try_b(try *t)
{
return t->b;
}
void trial(try *t)
{
t->a = 1;
t->b = 2;
}
main.c:
#include <stdio.h>
#include "api.h"
int main()
{
try *s_tryvar = alloc_try();
trial(s_tryvar);
printf("a = %d\nb = %d\n", try_a(s_tryvar), try_b(s_tryvar));
free_try(s_tryvar);
}
Think how the opaque FILE structure works in C. You only work with pointers, and you need a function like fopen() to create an instance, and a function like fclose() to dispose of it.
The problem is in main.c, the compiler hasn't seen the definition of struct try. Because of that, the compiler is limited to using pointers to struct try.
What you want to do is add two new functions to your API:
try *create_try();
void *destroy_try(try *t);
These functions will call malloc and free respectively.
If you don't want to limit your structure to only being allowed on the heap, you are going to have to give up on making it opaque.
There is a way to do something that technically is not exactly what you are asking for, but should serve the same purpose of keeping your structure opaque while supporting non-heap allocation.
in api.h, you state an opaque structure as follows:
struct trytag_opaque
{
char data[sizeof(int)*2];
};
if you wanted to be more opaque than that, you could calculate the maximum size of the structure required across any supported platform, and use:
struct trytag_opaque
{
char data[MAX_TRYTAG_SIZE];
};
Then your api.h function declarations would look like:
int try_a(struct trytag_opaque *t)
and your function code would look like:
int try_a(struct trytag_opaque *t_opaque) {
trytag *t = (trytag *)t_opaque;
...
}
and your main.c would look like:
#include "api.h"
int main() {
struct trytag_opaque t;
...
try_a(&t);
...
}
Related
this a reproducible example and not the entire code the entire code is too large..
my problem was that i had a structure that i created using malloc and i needed to access it from another function in another file, but i keep getting segfault...
header file
main.h
#ifndef main_a
#define main_a
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct cmd_s
{
int n;
} cmd_t;
extern cmd_t *ptr;
void push(char *line);
#endif
the main.c file
main.c
#include "main.h"
cmd_t *ptr = NULL;
int main(void)
{
cmd_t *ptr = malloc(sizeof(cmd_t));
ptr->n = 5;
push("line");
return (0);
}
and where i need to access the struct from named opcode.c
opcode.c
#include "main.h"
void push(char *line)
{
int new = ptr->n;
}
note that this is not the actual code the actual code has useful values, this is an example that contains the challenge i am facing
i tried to use static instead but i got the same error.
i'm still a novice in c programming..
and i don't want to change the way i created the structure, which is through malloc because another function depends on it... i just need to make that malloced structure accessible to another file in the program.
thanks.
int main(void)
{
cmd_t *ptr = malloc(sizeof(cmd_t));
You create new ptr variable visible only in function main. Your push see the global pointer ptr but not the one you have malloced.
You need to
int main(void)
{
ptr = malloc(sizeof(*ptr));
/* .... */
Use obiects not types in sizeof (as in this example)
The struct declaration in my main.c file. I have the function prototype declared but not shown.
typedef struct data
{
int t;
float tp, tf, tt;
} reactorData;
int main()
{
reactorData reactorOne[21];
//other stuff
}
This is the function giving me errors in my function.c file. Specifically in the printf() statement.
typedef struct data reactorData; //this is what I have up top
void reactorOutput(reactorData * data)
{
int c;
for (c=0;c<21;c++)
{
printf(" %3d\t %.0f\t %.0f\t %.0f\n",c, data[c].tp, data[c].tf, data[c].tt);
}
}
The error reads:
|error: invalid use of undefined type 'struct data'|
The function itself works perfectly fine/ I've tested it within main. Its only when I have it in functions.c it doesn't work.
New structs and type definition that must be shared across different compile units are best placed in a header file:
// mystructh.h
#ifndef MYSTRUCT_H
#define MYSTRUCT_H
typedef struct data
{
int t;
float tp, tf, tt;
} reactorData;
void reactorOutput(reactorData * data);
// other stuff
#endif
then in the other c files you have to include the header
main.c
#include <stdio.h>
#include "mystruct.h"
int main(void)
{
reactorData reactorOne[21];
// for example
reactorOutput(reactorOne);
//other stuff
}
functions.c
// functions.c
#include "mystruct.h"
void reactorOutput(reactorData * data)
{
int c;
for (c=0;c<21;c++)
{
printf(" %3d\t %.0f\t %.0f\t %.0f\n",c, data[c].tp, data[c].tf, data[c].tt);
}
}
The problem with your version is that struct data is only defined in main.c.
When the compiler compiles functions.c, it doesn't know what struct data is.
That's why you have to use header files live shown above.
Sorry for the title, I can't find words to describe my question in few words.
I already know that swift can use struct written in c. For example
In Bridging-Header.h
typedef struct {
int x;
int y;
} Pointer;
then I can use Pointer directly.
But in my case, I have a library written in C. There are many structs with hidden implement. For example:
In Briding-Header.h
typedef struct Pointer Pointer;
I can't use Pointer any more, got unknown type. In my library Pointer is used as
create_pointer(Pointer **pointer);
Any help is appreciated!
P.S I have no .h file which define struct Pointer. All details about Pointer is hide, access them by function, for example
int getx(Pointer *pointer);
Here is my full test code:
user_input.c
#include <stdio.h>
#include "user_input.h"
struct Pointer {
int x;
int y;
};
void get_user_input(int *user_input) {
scanf("%i", user_input);
}
void init_pointer(Pointer *point) {
point->x = 20;
point->y = 20;
}
user_input.h
#ifndef __user_input_h__
#define __user_input_h__
typedef struct Pointer Pointer;
void init_pointer(Pointer *p);
#endif
Bridging-Header.h
#include "user_input.h"
main.swift
import Foundation
var pointer:Pointer = Pointer(x:10, y:20)
Xcode give me this error: Pointer undefined
Bridging-Header.h
#include "user_input.h"
user_input.c
#include <stdlib.h>
struct Pointer {
int x;
int y;
};
Pointer *create_pointer() {
Pointer *p = malloc(sizeof(struct Pointer));
if (p) {
p->x = 20;
p->y = 20;
}
return p;
}
void delete_pointer(Pointer *p) {
free(p);
}
int pointer_x(Pointer *p) {
return p->x;
}
int pointer_y(Pointer *p) {
return p->y;
}
user_input.h
#ifndef __user_input_h__
#define __user_input_h__
typedef struct Pointer Pointer;
Pointer *create_pointer();
void delete_pointer(Pointer *p);
int pointer_x(Pointer *p);
int pointer_y(Pointer *p);
#endif
main.swift
import Foundation
var pointer: COpaquePointer = create_pointer()
println("\(pointer_x(pointer)), \(pointer_y(pointer))")
delete_pointer(pointer)
// Writing the wrapper class could be helpful.
class CPointer {
var _ptr: COpaquePointer
init() {
_ptr = create_pointer()
assert(_ptr, "Failed on create_pointer()")
}
deinit {
delete_pointer(_ptr)
}
var x: Int {
get { return Int(pointer_x(_ptr)) }
}
var y: Int {
get { return Int(pointer_y(_ptr)) }
}
}
var p = CPointer()
println("\(p.x), \(p.y)")
You should be OK if you include the original header where Pointer is typedef-ed in ___Bridging-Header.h
So for example if you have foo.h where you declare your struct and your functions, then instead of doing any additional typdef calls in your bridging header just #import foo.h
Then your Swift code should be able to see the symbols declared in foo.h
Update:
What you need:
Say "foo.h" is the header file where Pointer is typedef-ed. Also say that "foo.c" is the file where createPointer() is implemented.
You'll need to create a Swift project in Xcode. Add "foo.h" and "foo.c" to the project.
Add a header file to the project called "foo-Bridging-Header.h" (Sometimes Xcode asks if you want to create a Bridging Header when you add a .c or .m file to the project, but with the Developer Seed I haven't observed this to be consistent yet).
In "foo-Bridging-Header.h", you'll need to #include foo.h
Once you have done this, you should be able to call any of the symbols from "foo.h" from the "main.swift" file in your project.
For example, I have a Swift project. In this project I have a Swift file (main.swift), a C header (test.h), a C source file (test.c), and a Bridging Header (test-Bridging-Header.h).
Their contents are as follows:
test.h:
void
printFoo();
test.c:
#include <stdio.h>
#include "test.h"
void
printFoo() {
printf("foo\n");
}
test-Bridging-Header.h:
#import "test.h"
main.swift:
import Foundation
println("Hello, World!")
printFoo()
When run, this outputs:
Hello, World!
foo
After change my question, I got an answer.
When the struct implements in hidden, this is called "opaque"
so I can use COpaquePointer.
var pointer: COpaquePointer = COpaquePointer.null()
// some init code.
init_pointer(pointer);
I am trying to make the s_cord_print function visible in the cord_s.c file only. Currently the function is visible/runnable in main.c even when it is declared static.
How do I make the s_cord_print function private to cord_s.c?
Thanks!
s_cord.c
typedef struct s_cord{
int x;
int y;
struct s_cord (*print)();
} s_cord;
void* VOID_THIS;
#define $(EL) VOID_THIS=&EL;EL
static s_cord s_cord_print(){
struct s_cord *THIS;
THIS = VOID_THIS;
printf("(%d,%d)\n",THIS->x,THIS->y);
return *THIS;
}
const s_cord s_cord_default = {1,2,s_cord_print};
main.c
#include <stdio.h>
#include <stdlib.h>
#include "s_cord.c"
int main(){
s_cord mycord = s_cord_default;
mycord.x = 2;
mycord.y = 3;
$(mycord).print().print();
//static didn't seem to hide the function
s_cord_print();
return 0;
}
~
The problem is:
#include "s_cord.c"
You should remove that. Instead, create a s_cord.h file that contains only declarations, such as:
typedef struct s_cord{
int x;
int y;
struct s_cord (*print)();
} s_cord;
and put:
#include "s_cord.h"
in main.c and s_cord.c. You also need an extern declaration for s_cord_default. So the complete code is:
s_cord.c:
#include "s_cord.h"
#include <stdio.h>
void* VOID_THIS;
static s_cord s_cord_print(){
struct s_cord *THIS;
THIS = VOID_THIS;
printf("(%d,%d)\n",THIS->x,THIS->y);
return *THIS;
}
const s_cord s_cord_default = {1,2,s_cord_print};
s_cord.h:
typedef struct s_cord{
int x;
int y;
struct s_cord (*print)();
} s_cord;
#define $(EL) VOID_THIS=&EL;EL
extern const s_cord s_cord_default;
extern void *VOID_THIS;
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "s_cord.h"
int main(){
s_cord mycord = s_cord_default;
mycord.x = 2;
mycord.y = 3;
$(mycord).print().print();
return 0;
}
You'll now get a error if you try to call s_cord_print() from main, as expected.
EDIT: I forgot to move the $(EL) definition, and it needed an extern for VOID_THIS.
EDIT 2: The correct compilation command is:
gcc s_cord.c main.c -o main
When you include s_cord.c from within main.c, the compiler sees your program as one big file. It doesn't treat the included file as separate. To make them separate, you have to compile them separately. Once you have compiled them separately, you will then have to link them to create the whole program.
When you try to compile each part, you will get errors, because each file doesn't know about the code in the other file. Remember, this is what you were trying to accomplish with that one function. Well, now you've got what you asked for, many times over. Now, you have to create header files that explain the "missing parts". Generally the files being compiled look at each other's ".h" files (they #include them) to get a bearing on the "missing" (actually, external) parts. These are declarations, which tell the compiler "pretend you already know about this, and I promise that when we link everything, it will be provided".
I’m trying to figure out a way to use nested global structs as a sort of API namespacing for my C library.
Specifically, I want to expose a single Primary ‘namespacing struct,’ that contains other such structs (such as Primary.Secondary), that themselves contain function pointers (Primary.Secondary.a_function()).
I’ve abstracted out the following (relatively) simple example of what I want to do:
main.c:
#include "Primary.h"
int main () {
Primary.Secondary.a_function();
return 0;
}
Primary.h:
#if !defined(SECONDARY_H)
# include "Secondary.h"
#endif
struct Primary_struct {
struct Primary__Secondary_struct Secondary;
} extern Primary;
Primary.c:
#include "Primary.h"
struct Primary_struct Primary = {
.Secondary = Primary__Secondary
};
Secondary.h:
struct Primary__Secondary_struct {
void (*a_function) (void);
void (*another_function) (void);
} extern Primary__Secondary;
Secondary.c:
#include "Secondary.h"
#include <stdio.h>
void Primary__Secondary__a_function (void);
void Primary__Secondary__another_function (void);
struct Primary__Secondary_struct {
.a_function = Primary__Secondary__a_function,
.another_function = Primary__Secondary__another_function
} extern Primary__Secondary;
void Primary__Secondary__a_function(void) {
Primary.Secondary.another_function();
}
void Primary__Secondary__another_function(void) {
printf("run!\n");
}
When I attempt to compile this, I run into the following compiler error:
> C -O0 Primary.c Secondary.c main.c
Primary.c:3:33: error: initializer element is not a compile-time constant
struct Primary_struct Primary = {
^
1 diagnostic generated.
I should note, ideally, both the Primary and Primary__Secondary variables would be const. I was worried that the added complexity would exacerbate the problem… so for now, I’ve left that aspect out.
The problem seems to be that, for some reason, even when set as const, and containing only elements present at compile time, the Primary__Secondary struct is not a compile-time constant, and thus cannot be stored in another struct at compile-time. I can probably work around this by setting up all of the interfaces at runtime, but… that seems like a really hacky solution. I’m looking for any alternative solutions to this problem, that the more C-fu of you than I can come up with.
(Note: This is related to this question, but is substantially different, and quite a bit more specific.)
What you're trying can't be done; sorry. Here's a condensed example:
#include <stdio.h>
int a = 5;
int b = a;
int main(int argc, char *argv[])
{
printf("Hello, world!\n");
return 0;
}
Compiling this code gives the error:
main.c:4: error: initializer element is not constant
Because the compiler doesn't know how to make the assignment int b = a at compile time. It's just the way the language works!
You had some odd notations in your code - I've converted them to a more orthodox form. Also, as a general rule, avoid using double-underscore in names; in C++ this is absolutely necessary.
You also need to use a pointer to the embedded structure - then the code will run:
Primary.h
//Primary.h:
#ifndef PRIMARY_H
#define PRIMARY_H
#include "Secondary.h"
struct Primary_struct {
struct Primary_Secondary_struct *Secondary;
};
extern struct Primary_struct Primary;
#endif // PRIMARY_H
Secondary.h
//Secondary.h:
#ifndef SECONDARY_H
#define SECONDARY_H
struct Primary_Secondary_struct {
void (*a_function)(void);
void (*another_function)(void);
};
extern struct Primary_Secondary_struct Primary_Secondary;
#endif // SECONDARY_H
Primary.c
//Primary.c:
#include "Primary.h"
struct Primary_struct Primary = {
.Secondary = &Primary_Secondary
};
Secondary.c
//Secondary.c:
#include "Secondary.h"
#include "Primary.h"
#include <stdio.h>
void Primary_Secondary_a_function(void);
void Primary_Secondary_another_function(void);
struct Primary_Secondary_struct Primary_Secondary = {
.a_function = Primary_Secondary_a_function,
.another_function = Primary_Secondary_another_function
};
void Primary_Secondary_a_function(void) {
Primary_Secondary.another_function();
printf("hide!\n");
}
void Primary_Secondary_another_function(void) {
printf("run!\n");
}
main.c
//main.c:
#include "Primary.h"
int main () {
Primary.Secondary->a_function();
return 0;
}
This generates:
run!
hide!
I ended up going with a runtime approach, at least for now. I might try a pointers approach (suggested by Jonathan Leffler above) later on, and see if I end up with a less complex / more comprehensible codebase… but this works for now.
I use clang (and gcc)’s __attribute__((constructor)) extension to set up the structs’ relationships at runtime; the same could be achieved more portably (but less cleanly) with some code in main().
I’d offer a little more explanation, but it’s 4AM here… heh. I’ve spent all day on this >,<
main.c:
#include "Package.h"
int main () {
Package.One.a_function();
Package.One.another_function();
Package.Two.a_function();
Package.Two.another_function();
return 0;
}
Package.h:
#define PACKAGE_H
#if !defined(ONE_H)
# include "One.h"
#endif
#if !defined(TWO_H)
# include "Two.h"
#endif
// It seems this is broken, at least in `clang`
// #if __has_feature(attribute_constructor)
# define constructor __attribute__((constructor))
// #endif
struct Package_struct {
struct Package__One_struct One;
struct Package__Two_struct Two;
};
struct Package_struct extern Package;
Package.c:
#include "Package.h"
struct Package_struct Package = {};
One.h:
#define ONE_H
struct Package__One_struct {
void (*a_function) (void);
void (*another_function) (void);
};
struct Package__One_struct extern Package__One;
One.c:
#include "One.h"
#include "Package.h"
#include <stdio.h>
void Package__One__a_function (void);
void Package__One__another_function (void);
struct Package__One_struct Package__One = {
.a_function = Package__One__a_function,
.another_function = Package__One__another_function
};
void constructor Package__register_One(void) {
Package.One = Package__One; }
void Package__One__a_function(void) {
Package.One.another_function();
}
void Package__One__another_function(void) {
printf("one!\n");
}
Two.h:
#define TWO_H
struct Package__Two_struct {
void (*a_function) (void);
void (*another_function) (void);
};
struct Package__Two_struct extern Package__Two;
Two.c:
#include "Two.h"
#include "Package.h"
#include <stdio.h>
void Package__Two__a_function (void);
void Package__Two__another_function (void);
struct Package__Two_struct Package__Two = {
.a_function = Package__Two__a_function,
.another_function = Package__Two__another_function
};
void constructor Package__register_Two(void) {
Package.Two = Package__Two; }
void Package__Two__a_function(void) {
Package.Two.another_function();
}
void Package__Two__another_function(void) {
printf("two!\n");
}