I give the following example to illustrate my question:
1) a.h where the structure is declared
a.h
struct A_Structure;
typedef struct A_Structure *A_Structure_Ptr;
2) b.c where the structure definition is implemented
#include "a.h"
struct A_Structure
{
int a;
int b;
int c;
};
2) main.c where the structure is invoked
#include <stdlib.h>
#include "a.h"
int main ()
{
struct A_Structure b;
return 0;
}
However, I cannot compile these C codes as I receive the following error message:
>main.c(6): error C2079: 'b' uses undefined struct 'A_Structure'
Any ideas? Thank in advance.
EDIT:
#include <stdlib.h>
#include "a.h"
int main ()
{
struct A_Structure *b=0;
b=(struct A_Structure*)malloc(12);
b->a=3;
free(b);
return 0;
}
I tried to create the structure in this way but still failed.
You probably need this:
struct A_Structure
{
int a;
int b;
int c;
};
in a.h
This is the typical approach when defining structs
If you're trying to implement an opaque pointer, you need a function that instantiates A_Structure and returns a pointer, as well as functions that manipulate A_Structure pointers:
in a.h
A_Structure_Ptr CreateA(int a, int b, int c);
void FreeA(A_Structure_Ptr obj);
void SetA_a( A_Structure_Ptr obj, int a );
int GetA_a( A_Structure_Ptr obj );
// etc.
in b.c
A_Structure_Ptr CreateA(int a, int b, int c)
{
A_Structure_Ptr s = malloc( sizeof(A_Structure) );
s->a = a;
s->b = b;
s->c = c;
}
void FreeA(A_Structure_Ptr obj)
{
free( obj );
}
void SetA_a( A_Structure_Ptr obj, int a )
{
obj->a = a;
}
in main.c
int main ()
{
struct A_Structure *b = CreateA( 1, 2, 3);
SetA_a( b, 3 );
FreeA(b);
return 0;
}
When you put the structure declaration in a header file, but leave the definition in the .c file, this is known as using an opaque pointer API.
In an API like this, consumers only use pointers to the objects. Only the implementation needs to know the size or contents of the object. This is how you do OOP in C, and is key to information hiding which provides better decoupling of components. Here's a more complete example:
foo.h
struct foo; // forward declaration
struct foo *foo_create(void);
void foo_use(struct foo *f);
void foo_destroy(struct foo *f);
foo.c
#include <stdlib.h>
#include "foo.h"
struct foo {
int a, b, c; // Consumers don't know about these!
};
struct foo *foo_create(void)
{
struct foo *f = malloc(sizeof(*f));
if (!f)
return NULL;
*f = (struct foo) {
.a = 1,
.b = 2,
.c = 3,
};
return f;
}
void foo_use(struct foo *f)
{
// something with f->a, f->b
}
void foo_destroy(struct foo *f)
{
free(f);
}
main.c
#include "foo.h"
int main(void)
{
struct foo *f; // As a consumer of foo, we can only use **pointers**
f = foo_create();
if (!f)
return 1;
// I cannot access the members of `struct foo` here.
// In an opaque API, the struct members are considered
// an implementation detail and cannot be used outside
// of the implementation.
foo_use(f);
foo_destroy(f);
return 0;
}
You have to decide whether you want to hide the details of the structure from the "outside" or not. If you don't want to hide them, just put the structure definition in a.h. Hiding it ensures better decoupling and central control of your b.c over the content, but that means you have to provide a way to create an object in b.c (e.G.
struct A_Structure *create_A_Structure(void);
and use this from the outside.
an unrelated stylistic advice: better don't typedef pointers. While your _Ptr suffix makes it kind of obvious, it's still better to just have the asterisk everywhere because that is what C programmers are used to, so the fact that it's a pointer is obvious at the first glance.
I'd suggest something like this:
/* header */
typedef struct A A;
A *A_create(void);
/* implementation */
struct A
{
int foo;
}
A *A_create(void)
{
return malloc(sizeof(A));
}
Related
I have two forward declared functions and a struct:
int _bar(void*);
int _bar2(int);
typedef struct foo {
void* array[128];
int (*bar)(void* x) = _bar;
int (*bar2)(int x) = _bar2;
} FOO;
How can array be accessed from bar and bar2 in an arbitrary instance of FOO, such that array is mutable by each function? Can it be done?
And yes, I know it's easier and arguably better to just use something other than C to do this kind of thing. That's simply not the point, so please answer the question as asked, without an attempt to 'diagnose' some deeper problem like many replies here do.
You are trying to do OOP in C. You want bar and foo to be like C++ member function. You can't do that in C and you should't even try. Don't fight the language.
Just add a Foo parameter to the free functions:
typedef struct foo {
void* array[128];
} Foo;
int bar(/*const*/ Foo* foo, void*);
int bar2(/*const*/ Foo* foo, int);
You could do something like this:
#include <stdio.h>
typedef struct foo {
int array[128];
int(*bar)(struct foo* this, void* x);
int(*bar2)(struct foo* this, int x);
} FOO;
int _bar(FOO *this, void *p)
{
printf("bar2(%p)\n", p);
return 0;
}
int _bar2(FOO *this, int i)
{
printf("array[4] = %d\n", this->array[4]);
printf("bar2(%d)\n", i);
return i*2;
}
void ConstructFoo(struct foo *f)
{
for (int i = 0; i < sizeof(f->array) / sizeof(f->array[0]); i++)
f->array[i] = i;
f->bar = _bar;
f->bar2 = _bar2;
}
int main()
{
struct foo f;
ConstructFoo(&f);
printf ("%d\n", f.bar2(&f, 42));
}
I modified the type of array just for makeing the example simpler.
This example can be enhanced further depending on what you actually need, for example you could add function that set the bar and bar2 "member" functions to something else than _bar and _bar2.
I have 2 header files api.h and impl.h
api.h is visible to outside files and will be included in other ".c" files. So api.h includes impl.h
api.h defines 2 structures
typedef struct
{
uint32_t att;
union
{
struct
{
void* buffer;
size_t length;
} x;
struct
{
int a, b;
} v;
} content;
}dummy;
and impl.h has some other structures and function def which uses this structure.
I tried forward declaration but it doesn't help me .
Please help .
Actually, your dummy is not a structure, but a typedef to an unnamed structure. Try naming the structure, you can then forward-declare it:
typedef struct sdummy dummy; // forward declaration
void foo(dummy *);
struct sdummy { ... }; // definition
Either reorder your code in api.h so the type declaration precedes the #include "impl.h" or give your (currently anonymous) structure itself a name like dummy, dummy_, dummy_s so you can add a forward declaration
typedef struct dummy_ dummy;
to impl.h.
If you want to hide the details of your struct then you have to define it in some .c file, let's say impl.c, so that it has internal linkage to that compilation unit. To use it you have to expose create, destroy, getter and setter functions. So a basic setup would look like this:
api.h with forward declaration for your struct
// forward declaration
typedef struct dummy* dummy_t;
// create / destroy / setter / getter (omitted)
dummy_t alloc_dummy();
void free_dummy(dummy_t);
void set_number(dummy_t, int);
void set_string(dummy_t, char*);
void print_dummy(dummy_t);
Then comes impl.c
#include "api.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct dummy {
int n;
char* s;
};
dummy_t alloc_dummy()
{
return malloc(sizeof(struct dummy));
}
void free_dummy(dummy_t dummy)
{
if(dummy) {
free(dummy->s);
free(dummy);
}
}
void set_number(dummy_t dummy, int n)
{
if(dummy) {
dummy->n = n;
}
}
void set_string(dummy_t dummy, char* s)
{
if(dummy && s) {
dummy->s = strdup(s);
}
}
void print_dummy(dummy_t dummy)
{
if(dummy) {
printf("%d, %s\n", dummy->n, dummy->s);
}
}
And finally the usage in some other C files, here main.c
#include "api.h"
int main(int argc, char** argv)
{
// struct dummy d; // error! type is unknown
// instead use the create function
dummy_t d = alloc_dummy();
// d->n = 1; // error! dereference of unknown type
// instead use the setter function
set_number(d, 1);
set_string(d, "Hello, world!");
print_dummy(d);
free_dummy(d);
return 0;
}
Ouput
1, Hello, world!
If I have a struct in C that has an integer and an array, how do I initialize the integer to 0 and the first element of the array to 0, if the struct is a member another struct so that for every instance of the other struct the integer and the array has those initialized values?
Initialisers can be nested for nested structs, e.g.
typedef struct {
int j;
} Foo;
typedef struct {
int i;
Foo f;
} Bar;
Bar b = { 0, { 0 } };
I hope this sample program helps....
#include <stdio.h>
typedef struct
{
int a;
int b[10];
}xx;
typedef struct
{
xx x1;
char b;
}yy;
int main()
{
yy zz = {{0, {1,2,3}}, 'A'};
printf("\n %d %d %d %c\n", zz.x1.a, zz.x1.b[0], zz.x1.b[1], zz.b);
return 0;
}
yy zz = {{0, {0}}, 'A'}; will initialize all the elements of array b[10] will be set to 0.
Like #unwind suggestion, In C all instances created should initialized manually. No constructor kind of mechanism here.
You can 0-initialize the whole struct with {0}.
For example:
typedef struct {
char myStr[5];
} Foo;
typedef struct {
Foo f;
} Bar;
Bar b = {0}; // this line initializes all members of b to 0, including all characters in myStr.
C doesn't have constructors, so unless you are using an initializer expression in every case, i.e. write something like
my_big_struct = { { 0, 0 } };
to initialize the inner structure, you're going to have to add a function and make sure it's called in all cases where the structure is "instantiated":
my_big_struct a;
init_inner_struct(&a.inner_struct);
Here is an alternative example how you would do things like this with object-oriented design. Please note that this example uses runtime initialization.
mystruct.h
#ifndef MYSTRUCT_H
#define MYSTRUCT_H
typedef struct mystruct_t mystruct_t; // "opaque" type
const mystruct_t* mystruct_construct (void);
void mystruct_print (const mystruct_t* my);
void mystruct_destruct (const mystruct_t* my);
#endif
mystruct.c
#include "mystruct.h"
#include <stdlib.h>
#include <stdio.h>
struct mystruct_t // implementation of opaque type
{
int x; // private variable
int y; // private variable
};
const mystruct_t* mystruct_construct (void)
{
mystruct_t* my = malloc(sizeof(mystruct_t));
if(my == NULL)
{
; // error handling needs to be implemented
}
my->x = 1;
my->y = 2;
return my;
}
void mystruct_print (const mystruct_t* my)
{
printf("%d %d\n", my->x, my->y);
}
void mystruct_destruct (const mystruct_t* my)
{
free( (void*)my );
}
main.c
int main (void)
{
const mystruct_t* x = mystruct_construct();
mystruct_print(x);
mystruct_destruct(x);
return 0;
}
You don't necessarily need to use malloc, you can use a private, statically allocated memory pool as well.
In api.h
typedef void* hidden_my_type;
void do_something(my_type x);
In core.c
struct _my_type
{
int a;
}
void do_something(hidden_my_type void_x)
{
struct *_my_type x = void_x; /*Don't understand is that correct way to do, as I'm getting segmentation fault error */
printf("Value: %d\n", x->a);
}
Other way I thought as,
struct *_my_type x = (struct _my_type *)malloc(sizeof(struct _my_type));
void_x = x
printf(Value: %d\n", x->a);
But still I'm getting seg-fault error.
ok here is the problem with void*....
e.g.
in core.c
void init_my_type(hidden_my_type a)
{
my_type *the_a = malloc(...);
a = the_a // <<<<<<<<<<<<<<<<<<<<<<<<<<<< is this correct?! a is void* and the_a // is original type
pthread_cond_init(&the_a->...);
.. (in short any other methods for init ..)
}
void my_type_destroy(my_hidden_type x)
{
my_type *the_x = x;
pthread_detroy(&the_x-> ...);
}
in main.c
test()
{
my_hidden_type x;
init_my_type(x);
....
my_type_detroy(x);
}
this it self should fail. as in main.c test function, x is void* ... init will allocate but in destroy I'm again passing void* .. which can be anything!
EDIT (Solved for me)
In api.h
typedef void* hidden_my_type;
void do_something(my_type x);
In core.c
struct _my_type
{
int a;
}
void init_hidden_type(hidden_my_type void_p_my_type)
{
struct _my_type *real_my_type = (struct _my_type *)malloc(sizeof(struct _my_type));
//--- Do init for your type ---
void_p_my_type = real_my_type;
}
void do_something(hidden_my_type void_x)
{
struct *_my_type x = void_x;
printf("Value: %d\n", x->a);
}
Version 0 — Critique of Question's Code
The posted code does not compile.
api.h
typedef void* hidden_my_type;
void do_something(my_type x);
This defines hidden_my_type but not the my_type that is passed to do_something(). Presumably, you intended:
typedef void *my_type;
void do_something(my_type x);
core.c
struct _my_type
{
int a;
}
As noted below too, there is a semi-colon missing after the structure definition.
void do_something(hidden_my_type void_x)
{
struct *_my_type x = void_x;
printf("Value: %d\n", x->a);
}
You have the hidden_my_type vs my_type problem again. You have the * of the pointer where it cannot go; it must go after the struct _my_type. You probably intended something like:
void do_something(my_type void_x)
{
struct _my_type *x = void_x;
printf("Value: %d\n", x->a);
}
This is now syntactically correct (I think; I haven't actually run it past a compiler). You have not shown how it is used; indeed, since the user code has no way to generate a pointer to a valid structure, there is no way for this code to be used safely.
Your test code (unshown — why don't you show your test code) might look something like this:
#include "api.h"
int main(void)
{
my_type x = 0;
do_something(x);
return 0;
}
Alternatively, it might not have the = 0 initializer in place. Either way, your code is unable to function sanely, and a core dump is almost inevitable. When you hide the structure from the user, you have to provide them with a mechanism to get hold of a valid (pointer to) the structure, and you've not done that.
Version 1
This is a better way to do it, because it is more nearly type-safe:
api.h version 1
typedef struct _my_type *my_type;
void do_something(my_type x);
core.c version 1
#include "api.h"
struct _my_type
{
int a;
};
Note the added semi-colon, and the include of the api.h file.
void do_something(my_type x)
{
// Now you don't have to do casting here!
//struct *_my_type x = void_x; /*Don't understand is that correct way to do, as I'm getting segmentation fault error */
printf("Value: %d\n", x->a);
}
Version 2
Actually, we can debate the wisdom of hiding the pointer; I would prefer not to do so:
api.h version 2
#ifndef API_H_INCLUDED
#define API_H_INCLUDED
typedef struct my_type my_type;
extern void do_something(my_type *x);
extern my_type *my_type_initializer(void);
extern void my_type_release(my_type *x);
#endif /* API_H_INCLUDED */
core.c version 2
#include "api.h"
#include <stdio.h>
#include <stdlib.h>
struct my_type
{
int a;
};
void do_something(my_type *x)
{
printf("Value: %d\n", x->a);
}
my_type *my_type_initializer(void)
{
my_type *x = malloc(sizeof(*x));
x->a = 57; // More plausibly, this would be 0
return x;
}
void my_type_release(my_type *x)
{
free(x);
}
main.c
#include "api.h"
int main(void)
{
my_type *x = my_type_initializer();
do_something(x);
my_type_release(x);
return 0;
}
That's nice and clean. Of course, the user cannot allocate a struct my_type (only a pointer to it), so you need a function to allocate the structure for them. Think of the Standard C Library, and the FILE type, and fopen() to allocate and fclose() to release and fprintf() etc to manipulate the type. The my_type_initializer() is functioning as an analogue to fopen(), my_type_release() as an analogue to fclose(), and do_something() as an analogue to fprintf().
Jonathan, you beat me to an answer, but this may be helpful as well. Here, api.c contains the (private) implementation, and api.h provides the interface to be consumed by other code such as main.c.
// main.c: uses only the public interface to the private code
#include "api.h"
int main(int argc, char *argv[]) {
void *foo;
foo = create_foo("five", 5);
print_foo(foo);
delete_foo(foo);
}
// EOF main.c
// api.h: the public interface
#ifndef _api_h_
#define _api_h_
void *create_foo(char *name, int number);
void print_foo(void *foo);
void delete_foo(void *foo);
#endif // _api_h_
// api.c: the private implementation
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// The real structure is private to the implementation.
typedef struct {
char name[20];
int number;
} real_struct;
// Create a new structure, initialize, return as ptr-to-void.
void *create_foo(char *name, int number) {
real_struct *s = malloc(sizeof(real_struct));
strcpy(s->name, name);
s->number = number;
return (void *) s;
}
// Print the data.
void print_foo(void *foo) {
real_struct *s = (real_struct *) foo;
printf("name: %s, number: %d\n", s->name, s->number);
}
// Release the memory.
void delete_foo(void *foo) {
free(foo);
}
// EOF api.c
This code should compile and run:
$ gcc -o foo main.c api.c
$ ./foo
name: five, number: 5
I have the follwing C function. How should I wrap it so it can be called from a Lua script?
typedef struct tagT{
int a ;
int b ;
} type_t;
int lib_a_f_4(type_t *t)
{
return t->a * t->b ;
}
I know how to wrapr it if the function parameter type were int or char *. Should I use table type for a C structure?
EDIT: I am using SWIG for the wraping , according to this doc, It seems that I should automatically have this function new_type_t(2,3) , but it is not the case.
If you wrap a C structure, it is also
mapped to a Lua userdata. By adding a
metatable to the userdata, this
provides a very natural interface. For
example,
struct Point{ int x,y; };
is used as follows:
p=example.new_Point()
p.x=3
p.y=5
print(p.x,p.y) 3 5
Similar access is provided for unions
and the data members of C++ classes. C
structures are created using a
function new_Point(), but for C++
classes are created using just the
name Point().
I put this together in a hurry. It compiled; then I did a few last-minute edits. I hope it's close to the right thing. Go through the Lua manual and look at all the unfamiliar functions.
#include <lua.h>
#include <lauxlib.h>
const char *metaname = "mine.type_t"; // associated with userdata of type type_t*
typedef struct tagT{
int a ;
int b ;
}type_t;
int lib_a_f_4(type_t *t)
{
return t->a * t->b ;
}
static int lua_lib_a_f_4(lua_State *L) {
type_t *t = luaL_checkudata(L, 1, metaname); // check argument type
lua_pushnumber(L, (lua_Number)lib_a_f_4(t));
return 1;
}
static int lua_new_t(lua_State *L) { // get Lua to allocate an initialize a type_t*
int a = luaL_checkint(L, 1);
int b = luaL_checkint(L, 2);
type_t *t = lua_newuserdata(L, sizeof(*t));
luaL_getmetatable(L, metaname);
lua_setmetatable(L, -2);
t->a = a;
t->b = b;
return 1;
}
static const struct luaL_reg functions[] = {
{ "lib_a_f_4", lua_lib_a_f_4 },
{ "new_t", lua_new_t },
{ NULL, NULL }
};
int mylib_open(lua_State *L) {
luaL_register(L, "mylib", functions);
luaL_newmetatable(L, metaname);
lua_pop(L, 1);
return 1;
}
//compile and use it in lua
root#pierr-desktop:/opt/task/dt/lua/try1# gcc -shared -o mylib.so -I/usr/include/lua5.1/ -llua *.c -ldl
root#pierr-desktop:/opt/task/dt/lua/try1# lua
Lua 5.1.3 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> require("mylib")
> t=mylib.new_t(2,3)
> mylib.lib_a_f_4(t)
> print(mylib.lib_a_f_4(t))
6
>
Solved.
Should also add the type definition in the example.i file , just include the .h is not enough.
%module example
%{
#include "liba.h"
%}
void lib_a_f_1(void);
int lib_a_f_2(int a, int b);
int lib_a_f_3(const char *s);
int lib_a_f_4(struct Point *t);
struct Point{
int a;
int b;
};
use example.Point() ,not example.new_Point() (SWIG Version 1.3.35)
example.Point()
f=example.Point()
f.a=2
f.b=3
example.lib_a_f_4(f)
print(example.lib_a_f_4(f))