I'm trying to "implement" a cross-platform mutex following the instructions here:
And here is my code:
#ifndef __SIMPLEAV_CORE_UTIL_SAMUTEX_H_DEFINED__
#define __SIMPLEAV_CORE_UTIL_SAMUTEX_H_DEFINED__
/*
* A simple cross-platform (currently only on linux and win) mutex.
*
* usage:
* SAMutex mutex;
* SAMutex_init(&mutex);
* SAMutex_lock(&mutex);
* SAMutex_unlock(&mutex);
* SAMutex_destroy(&mutex);
*
* all functions return 0 on success, -1 on error.
*/
#if defined(LINUX)
#include <pthread.h>
//typedef pthread_mutex_t SAMutex;
#define SAMutex pthread_mutex_t
#elif defined(WINDOWS)
#include <windows.h>
#include <process.h>
//typedef HANDLE SAMutex;
#define SAMutex HANDLE
#endif
int SAMutex_init(SAMutex *);
int SAMutex_lock(SAMutex *);
int SAMutex_unlock(SAMutex *);
int SAMutex_destroy(SAMutex *);
#endif
but what I got after running gcc was:
~/git/SimpleAV/build $ make
[ 20%] Building C object CMakeFiles/player2.dir/player2.c.o
In file included from /home/wecing/git/SimpleAV/include/SimpleAV/core/core.h:4,
from /home/wecing/git/SimpleAV/include/SimpleAV/SDL/api.h:5,
from /home/wecing/git/SimpleAV/player2.c:4:
/home/wecing/git/SimpleAV/include/SimpleAV/core/util/SAMutex.h:28: error: expected ‘)’ before ‘*’ token
/home/wecing/git/SimpleAV/include/SimpleAV/core/util/SAMutex.h:29: error: expected ‘)’ before ‘*’ token
/home/wecing/git/SimpleAV/include/SimpleAV/core/util/SAMutex.h:30: error: expected ‘)’ before ‘*’ token
/home/wecing/git/SimpleAV/include/SimpleAV/core/util/SAMutex.h:31: error: expected ‘)’ before ‘*’ token
In file included from /home/wecing/git/SimpleAV/include/SimpleAV/SDL/api.h:5,
from /home/wecing/git/SimpleAV/player2.c:4:
/home/wecing/git/SimpleAV/include/SimpleAV/core/core.h:28: error: expected specifier-qualifier-list before ‘SAMutex’
make[2]: *** [CMakeFiles/player2.dir/player2.c.o] Error 1
make[1]: *** [CMakeFiles/player2.dir/all] Error 2
make: *** [all] Error 2
by the way, on linux, pthread_mutex_t is defined as:
typedef union
{
struct __pthread_mutex_s
{
int __lock;
unsigned int __count;
int __owner;
#if __WORDSIZE == 64
unsigned int __nusers;
#endif
/* KIND must stay at this position in the structure to maintain
binary compatibility. */
int __kind;
#if __WORDSIZE == 64
int __spins;
__pthread_list_t __list;
# define __PTHREAD_MUTEX_HAVE_PREV 1
#else
unsigned int __nusers;
__extension__ union
{
int __spins;
__pthread_slist_t __list;
};
#endif
} __data;
char __size[__SIZEOF_PTHREAD_MUTEX_T];
long int __align;
} pthread_mutex_t;
What did I do wrong?
have you defined LINUX or WINDOWS define in your Makefile?
try
gcc -dM -E - < /dev/null
this prints all the predefined macros.
and here the windows macros.
It looks that gcc doesn't see the macro definition in the #ifdef. I think __linux__ is the correct macro to test. Or even better test for the macros from POSIX and not for Linux alone.
Edit: Probably the best is test for _XOPEN_SOURCE. POSIX imposes that this is defined before any header is included.
Related
I am trying to move some functions to separate file in c project.
I made util.h file with
#ifndef _UTIL_H
#define _UTIL_H
#include <signal.h>
#include <termios.h>
#include <time.h>
...
extern struct timeval tv1, tv2, dtv;
void time_start();
long time_stop();
and I made util.c file with
#include "util.h"
...
struct timeval tv1, tv2, dtv;
void time_start() { gettimeofday(&tv1, &timezone); }
long time_stop()
{
gettimeofday(&tv2, &timezone);
dtv.tv_sec = tv2.tv_sec - tv1.tv_sec;
...
in cmake I have
add_executable(mpptd mpptd.c util.c)
and I get the following errors during compile
[build] ../settings/daemons/util.c: In function ‘time_stop’:
[build] ../settings/daemons/util.c:14:8: error: invalid use of undefined type ‘struct timeval’
[build] dtv.tv_sec = tv2.tv_sec - tv1.tv_sec;
[build] ^
and
[build] ../settings/daemons/util.c: At top level:
[build] ../settings/daemons/util.c:7:16: error: storage size of ‘tv1’ isn’t known
[build] struct timeval tv1, tv2, dtv;
[build] ^~~
What can be wrong here? Why "storage size" error goes later than "undefined type" error? Whouldn't it go earlier?
struct timeval is defined in sys/time.h. You'll need to include that.
#ifndef _UTIL_H
#define _UTIL_H
#include <signal.h>
#include <termios.h>
#include <time.h>
#include <sys/time.h>
...
The struct definition (the part with struct { .. }) must be visible to code using that struct. Simply put that part in a header visible to the code using the struct, then include that header.
Otherwise the struct ends up as a forward declaration, of incomplete type. Incomplete types don't have any size, hence the cryptic errors.
In this case you seem to be using some non-standard, non-POSIX (or possibly obsolete POSIX?) library. Strict compilers (like gcc in -std=c11 -pedantic-errors mode) won't allow non-standard crap in standard headers, so you'll have to include the specific non-standard header separately, the struct won't be found in time.h.
When I compile the program, outlined below, I am getting the following error(s) back
[igor#localhost ~/I2C]$ make i2c_VIPER DEFINE=-DVIPER
gcc -g -Wall -D__USE_FIXED_PROTOTYPES__ -DVIPER -ansi -lusb -c -o i2c.o i2c.c
In file included from i2c.c:9:
viperboard.h:120: error: expected ‘)’ before ‘*’ token
i2c.c: In function ‘main’:
i2c.c:32: error: ‘usb_dev’ undeclared (first use in this function)
i2c.c:32: error: (Each undeclared identifier is reported only once
i2c.c:32: error: for each function it appears in.)
i2c.c:33: warning: implicit declaration of function ‘i2c_VIPER’
make: *** [i2c.o] Error 1
I've tried many things, more or less semi-blindly, to make it working. The struct parsed_CLI_I2C_t defined by me, works flawlessly. No compilation errors. But, when I try to use struct usb_device from <usb.h> in equivalent way, the compiler is not happy.
What I am doing wrong ?
Relatively detailed description follows.
Let's start with a code snippet from the standard #include < usb.h > <-- link to the full header file
/* Data types */
struct usb_device;
struct usb_bus;
struct usb_device {
struct usb_device *next, *prev;
char filename[PATH_MAX + 1];
struct usb_bus *bus;
struct usb_device_descriptor descriptor;
struct usb_config_descriptor *config;
void *dev; /* Darwin support */
u_int8_t devnum;
unsigned char num_children;
struct usb_device **children;
};
Here is the first local header file #include "viperboard.h"
struct parsed_CLI_I2C_t;
extern int i2c_VIPER (struct usb_device **usb_dev, struct parsed_CLI_I2C_t **CLI_I2C_options);
extern bool OpenDevice(void);
This is the second local header file #include "I2C.h"
typedef struct
{
char *USB_board;
int query;
int write_type;
} parsed_CLI_I2C_t;
extern int parse_CLI_I2C_options (int argc, char *argv[], parsed_CLI_I2C_t **CLI_I2C_options);
The main program looks like this
/* all other standard include stuff skipped for brevity */
#include <usb.h>
#include "viperboard.h"
#include <stdbool.h>
#include "I2C.h"
int main(int argc, char *argv[])
{
parsed_CLI_I2C_t *CLI_I2C_options;
parse_CLI_I2C_options (argc, argv, &CLI_I2C_options);
struct usb_device *usb_dev;
i2c_VIPER (&usb_dev, &CLI_I2C_options);
}
and, finally, this is the external module
i2c_VIPER.c
/* all other standard include stuff skipped for brevity */
#include <usb.h>
#include "viperboard.h"
#include <stdbool.h>
#include "I2C.h"
int i2c_VIPER (struct usb_device **usb_dev, struct parsed_CLI_I2C_t **CLI_I2C_options )
{
bool connected; /* True if the ViperBoard is connected */
connected = OpenDevice();
return(0);
}
This is
OpenDevice.c
#include <stdbool.h>
#include <usb.h>
bool OpenDevice() /* <---- this is line 11 */
{
usb_set_debug( 0 );
/* Initialize USB library */
usb_init( );
etc etc etc
return true;
}
========================================================
30 minutes later: all suggested changes implemented
Another type of error appeared.
OpenDevice.c:11: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘OpenDevice’
make: *** [OpenDevice.o] Error 1
This line
usb_device *usb_dev; /* this is line 32 */
will not work as you're compiling a C program, not a C++ program. In C structures are not automatically types like they are in C++. You need to use the struct keyword to declare structures:
struct usb_device *usb_dev; /* this is line 32 */
This change you have to do for every place where you use structures, for example like the declaration and definition of the i2c_VIPER function.
Also note that for the bool type to work, you need to include <stdbool.h>.
As part of getting familiar with GObject I'm trying to create a "Hello, world" interface following the example in the reference manual. Here's what I have in hello_world_if.h:
#ifndef __HELLO_WORLD_IF_H__
#define __HELLO_WORLD_IF_H__
#include <glib-object.h>
G_BEGIN_DECLS
#define TYPE_HELLO_WORLD_IF (hello_world_if_get_type())
#define HELLO_WORLD_IF(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_HELLO_WORLD_IF, HelloWorldIf))
#define IS_HELLO_WORLD_IF(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_HELLO_WORLD_IF))
#define HELLO_WORLD_IF_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), TYPE_HELLO_WORLD_IF, HelloWorldIfInterface))
typedef struct _HelloWorldIf HelloWorldIf; /* dummy object */
typedef struct _HelloWorldIfInterface HelloWorldIfInterface;
struct _HelloWorldIfInterface {
GTypeInterface parent;
gchar *(*get_hello)(HelloWorldIf *self);
};
GType hello_world_if_get_type(void);
gchar *hello_world_if_get_hello(HelloWorldIf *self);
G_END_DECLS
#endif /* __HELLO_WORLD_IF_H__ */
and in hello_world_if.c:
#include "hello_world_if.h"
G_DEFINE_INTERFACE(HelloWorldIf, hello_world_if, 0);
static void
hello_world_if_default_init(gpointer g_class) {
/* Add properties and signals to the interface here */
}
gchar *
hello_world_if_get_hello(HelloWorldIf *self) {
g_return_if_fail(IS_HELLO_WORLD_IF(self));
HELLO_WORLD_IF_GET_INTERFACE(self)->get_hello(self);
}
But this doesn't compile:
$ make
gcc -g -pthread -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -c -o hello_world_if.o hello_world_if.c
hello_world_if.c:3: error: expected declaration specifiers or ‘...’ before ‘hello_world_if’
hello_world_if.c:3: error: expected declaration specifiers or ‘...’ before numeric constant
hello_world_if.c:3: warning: data definition has no type or storage class
make: *** [hello_world_if.o] Error 1
From reading other answers here it seems this "expected declaration specifiers" message often means a necessary header file hasn't been included or has been included too late. But I'm not sure how that could be the case here. (Specifically, adding #include <glib.h> or #include <glib-object.h> to the C file doesn't change anything.)
I must be missing something simple but I just don't see it. Help?
Turns out there's a simple explanation: The G_DEFINE_INTERFACE macro was added in GLib 2.24.0, but I'm using version 2.22.5 (the standard on CentOS 6.3). I'll need to either build and install a newer version of GLib or dig up older reference documentation—the website doesn't go back further than 2.26.1.
If i compile the below program with std=c99, i get an error, but the program compiles fine without the c99 flag. Why?
#include <signal.h>
void x()
{
sigset_t dd;
}
int main(void)
{
x();
return 0;
}
jim#cola temp]$ gcc -std=c99 blah.c -o blah
blah.c: In function ‘x’:
blah.c:9: error: ‘sigset_t’ undeclared (first use in this function)
blah.c:9: error: (Each undeclared identifier is reported only once
blah.c:9: error: for each function it appears in.)
blah.c:9: error: expected ‘;’ before ‘dd’
Because sigset_t is not part of <signal.h> in standard C and you requested strict standards compatibility with -std=c99. That is, a strictly standard C program can do:
#include <signal.h>
int sigset_t;
int main(void) { return 0; }
and expect it to work.
sigset_t is not in C99 standard, but it is available in POSIX. You can define _POSIX_SOURCE or _POSIX_C_SOURCE to make sigset_t available.
Here is the definition:
#define _NSIG 64
#define _NSIG_BPW 32
#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
typedef unsigned long old_sigset_t; /* at least 32 bits */
typedef struct {
unsigned long sig[_NSIG_WORDS];
} sigset_t;
Also see What does #define _POSIX_SOURCE mean?
I'm compiling grep on the 64-bit GCC compiler for Windows 7 x64 SUA/Interix.
It chokes on the marked line in stddef.h:
#ifndef _SIZE_T_DEFINED
#if defined (lp64) || defined(_WIN64)
#ifdef lp64
typedef unsigned long size_t; // <------ error
#else /* lp64 */
typedef unsigned __int64 size_t;
#endif /* lp64 */
#else /* (defined(lp64) || defined(_WIN64)) */
typedef unsigned int size_t;
#endif /* (defined(lp64) || defined(_WIN64)) */
#define _SIZE_T_DEFINED
#define _SIZE_T
#endif /* _SIZE_T_DEFINED */
The output for make is:
make all-recursive
Making all in intl
gcc -c -DLOCALEDIR=\"/usr/local/share/locale\" -DLOCALE_ALIAS_PATH=\"/usr/local/share/locale\" -DLIBDIR=\"/usr/local/lib\" -DIN_LIBINTL -DHAVE_CONFIG_H -I.. -I. -I../../intl -D_ALL_SOURCE -D_REENTRANT -I/usr/local/include -I/usr/local/include -D_ALL_SOURCE -D_REENTRANT ../../intl/intl-compat.c
In file included from ../../intl/gettextP.h:23:0,
from ../../intl/intl-compat.c:25:
/usr/include/stddef.h:50:23: error: duplicate 'unsigned'
*** Error code 1
Stop in /tmp/grep-2.5.4-src/build/intl.
*** Error code 1
Stop in /tmp/grep-2.5.4-src/build (line 329 of Makefile).
*** Error code 1
Stop in /tmp/grep-2.5.4-src/build (line 244 of Makefile).
I don't understand what the cause is... it's already confusing that long is being used as though it's 64-bit in GCC, but the error is even more confusing! Ideas?
Somewhere in your code, somone probably did:
#define size_t unsigned long
Or something along those lines, without having defined _SIZE_T_DEFINED when they did it. Then their code #includes stddef.h via the path listed in your error message. That makes your error line look like:
typedef unsigned long unsigned long;
To the compiler, which is not going to work!