I still struggling to compile a C console application, the compiling procedure still failing with the error below:
"Main.c", line 51: error #2040: expected an identifier
extern "C" void TreatReceivedSignal( int NoSignal ) ;
^
1 error detected in the compilation of "Main.c".
gmake: *** [Main.o] Error 2
below the declaration of the extern method on the C code :
extern "C" void TreatReceivedSignal( int NoSignal ) ;
I am using HP-UX aCC compiler [HP C/aC++ B3910B A.06.26], also I switched on the compilation flag -Ae to enable C99 support.
Seems that the compiler cannot recognize the 'extern "C"' as C reserved word, may some other compilation flag need to be set.
Any idea please that can solve this kind of issue?
Thank you very much in advance.
Regards
The extern "C" construct is a C++ specific thing, it can't be used in C. And the compiler treats your source file as a C source file since it has the extension .c.
The most common thing to do is to use the preprocessor to conditionally add this for C++ compilations:
#ifdef __cplusplus
extern "C" {
#endif
/* Standard C prototypes */
#ifdef __cplusplus
}
#endif
Related
I failed to define overloading functions with error message of error: conflicting declaration of C function if enclosing by #ifdef __cplusplus blocks.
Below is a simple code for an easy view. This piece of code worked fine without #ifdef __cplusplus blocks.
However, my project code does need #ifdef __cplusplus as it involves combination of C and C++ codes.
Command lines after #ifdef __cplusplus block should be C++, why did it fail to define the overloading function? How to fix this problem with presence of #ifdef __cplusplus blocks?
#include <iostream>
using namespace std;
#ifdef __cplusplus
extern "C"
{
#endif
int add(int x)
{
return x;
}
int add(int x, int y)
{
return x + y;
}
int main() {
// cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
int X = add(2);
int Z = add(8,2);
cout <<X<<" "<<Z<<endl;
return 0;
}
#ifdef __cplusplus
}
#endif
Command lines after #ifdef __cplusplus block should be C++
First of all, I believe you have a misconception of #ifdef __cplusplus, this macro only checks if your compiler is a C++ compiler or not.
You rather need focus on extern "C" {}. This block of code explicitly tells your compiler, that codes inside this block must be in C language(not C++).
This is important since C and C++ have different mechanisms of storing and calling functions from binary. (Called name mangling). Better to say, C and C++ binaries are not compatible. So extern "C" will tell your compiler that your functions C codes, and those function names are not mangled.
So #ifdef __cplusplus checks if your code is C or C++; if your code is in C++, insert extern "C" { that tells your compiler that those codes in this block are C code.
And since function overloading is not a part of C language, your compiler will cause an error inside that block. (This matters with name mangling).
But this macro is mostly used in header files, not source files. Because the purpose of this macro is to enable your code to be included in both C and C++ code, but source files cannot be and must not be included by another source.
I'm trying to declare a global function accessible through different *.c files.
I have declared it in param.hxx, defined it in param.cxx and I would like to access it in compute_grid.c.
Unfortunately, during the compilation I have the following error :
compute_grid.c:(.text+0x5) : undefined reference to « grid_create »
I'm not very familiar with such functions declarations in C. Actually I'm building a module part of a big program, I've copied those declaration from another file of the code witch seems to work ?!
Unfortunately, the program is hugely confidential, I don't have access to all the sources but I will do my best to give you expurged parts...
param.hxx :
typedef struct grid_t
{
int *test;
} grid_t;
void
grid_create(void);
extern grid_t *grid;
param.cxx :
#include <malloc.h>
#include "param.hxx"
grid_t *grid;
void grid_create(void)
{
grid = (grid_t*)malloc(sizeof(grid_t));
grid->test = (int*)malloc(sizeof(int));
*grid->test = 123;
}
compute_grid.c :
#include "param.hxx"
void
compute_grid()
{
grid_create();
return;
}
Thank you for your help !
.cxx is one of the extensions used for C++ files. Your compiler may be using the extension of the file to compile the source as C++. When the C file is compiled, it generates an unresolved reference to the C symbol grid_create, but the compiled C++ file defines grid_create as a C++ symbol. Thus, the linker will leave the C symbol reference to grid_create unresolved, since there is only a C++ symbol associated with void grid_create(void).
You can try to guard the header file so that the C++ compiler will generate a C symbol rather than a C++ one.
#ifdef __cplusplus
extern "C" {
#endif
void
grid_create(void);
#ifdef __cplusplus
}
#endif
I have tried to google the errors but to no avail. Maybe I am searching in the wrong direction.
I am trying to compile a file but when i tired to compiled it, the compiler gave me these errors:
C2059 syntax error: ';'
C2059 syntax error: '}'
C2061 syntax error: identifier 'namespace_name'
C2449 syntax error: found '{' at file scope (missing header?)
In my code.c file:
#ifndef myclass_c
#define myclass_c
#include "classA.h"
#include "classB.h"
#include "conversionLib.h" // no namespace is being used here
namespace namespace_name {
// ... generated codes in C....
}
#endif
In classA.h and in classB.h:
#ifndef myclassA_h // myClassB_h if in classB
#define myclassA_h // myClassB_h if in classB
#include "classC.h" // both classA and classB include classC.h
namespace namespace_name {
#ifdef __cplusplus
extern "C" {
#endif
// ... generated codes in C....
#ifdef __cplusplus
}
#endif
}
#endif
and in classC.h (same for classD.h)
#ifndef myclassC_h // myclassD.h for classD.h
#define myclassC_h // myclassD.h for classD.h
#include "classD.h" // no includes in classD.h
namespace namespace_name {
#ifdef __cplusplus
extern "C" {
#endif
// ... generated codes in C....
#ifdef __cplusplus
}
#endif
}
#endif
what am i doing wrong? or have i missed out something?
Any suggestion would be greatly appreciated.
I apologized if this question/format is confusing.
Thanks in advance
The main problem seems to be, that you use c++ syntax in a .c file.
C does not support namespaces!
It does not make much sense to put a extern "C" function into an namespace. in C++ the compiler does something called 'name mangeling' it actually puts the name space (e.g. the class name, the namespace) and additional information (like function or template parameter) of an identifier into its symbol name that is the input to the linker.
extern "C" tells the C++ Compiler not to do so. so you lose the binding to the surrounding namespace (as well as the possibilities to overload the function).
It may be a nice thought to put the functions in a special namespace if they are included from C++ but on the other hand mostly in C namespaces are build y using a special prefix to the function name. so in C++ you end up with the explicit c++ name space and the implicit function prefix name space.
If you still want a namespace in c++ around your C-Functions you have to include the namespace definition into your #ifdef __cplusplus blocks. (but i do not even know if this is allowed by the C++ standard)
I am getting the following error while compiling my source code:
Compiling lib/netapi/joindomain.c
cc: "include/smb_ldap.h", line 33: error 1584: Inconsistent type declaration: "ber_tag_t".
cc: "include/smb_ldap.h", line 34: error 1713: Illegal redeclaration for identifier "ber_int_t".
The following command failed:
)
*** Error exit code 1
The corresponding code which flags the error is:
if HAVE_LBER_H
#include <lber.h>
#if defined(HPUX) && !defined(_LBER_TYPES_H)
#ifndef ber_tag_t
typedef unsigned long ber_tag_t;
typedef int ber_int_t;
#endif
#endif
I request help in understanding the root cause of this error.
Thanks in advance.
Here are my machine and compiler details for reference:
$ uname -a
HP-UX cifsvade B.11.31 U 9000/800 3751280844 unlimited-user license
$ which cc
/usr/bin/cc
$ ls -lrt /usr/bin/cc
lrwxr-xr-x 1 root sys 17 Oct 8 17:45 /usr/bin/cc -> /opt/ansic/bin/cc
$
lber.h defines ber_tag_t and ber_tag_t as follow:
typedef impl_tag_t ber_tag_t;
typedef impl_int_t ber_int_t;
In your code you try to redefine them, this is the case.
A condition
#ifndef ber_tag_t
is always true unless you defined ber_tag_t somewhere like
#define ber_tag_t smth
As oleg_g hints towards you are mixing preprocessor commands (#define) and c++ typedef
The preprocessor directives (#define etc.) are processed before the parser processes the resulting code. When you typedef ber_tag_t the preprocessor commands will never know of this and instead you need to #define a variable to indicate the type is defined.:
#if HAVE_LBER_H
#include <lber.h>
#if defined(HPUX) && !defined(_LBER_TYPES_H)
#ifndef DEFINED_BER_TAG_T
#define DEFINED_BER_TAG_T
typedef unsigned long ber_tag_t;
typedef int ber_int_t;
#endif
#endif
To clarify; preprocessor directives see only of other preprocessor variables as your code has not yet been interpreted at this point.
EDIT:
I should also mention it may be beneficial to lay out your code in a way to avoid the need of this if possible. For example using a separate common header in which the inclusion and type are protected by include guards for example.
I was doing code porting from Linux to Windows. I am using Visual Studio environment. I am stuck with one problem.
There is a function call with 2 parameters for Acquire and Release a semaphore in Windows.
The Linux code has one parameter
Windows:
KeInitializeSpinLock(spinlock,oldIRQL);
Linux
spin_lock_init(spinlock);
I have generic call like which I have to use :
Get_Lock(spinlock);
How do I do this for windows without changing the prototype of Get_Lock ?
I tried the following :
#define Get_Lock(lock) \
KIRQL oldIrql;\
KeAcquireSpinLock(&(lock),&oldIrql);
#define Release_Lock(sync) KeReleaseSpinLock(&(sync),oldIrql)
But the compiler is giving errors .. Basically I want to retain the value of oldIrql because that value is needed for KeReleaseSpinLock
Error
error C2275: 'KIRQL' : illegal use of this type as an expression
error C2146: syntax error : missing ';' before identifier 'oldIrql'
error C2065: 'oldIrql' : undeclared identifier
error C2065: 'oldIrql' : undeclared identifier
error C2065: 'oldIrql' : undeclared identifier
KIRQL is defined as
typedef UCHAR KIRQL
What wrong am I doing here ? Or Is there any other method which is there which can be used without changing the prototype of the Get_Lock and Release_Lock?
The problem is due to Microsoft compiler's only supporting C89 standard, which does not allow the intermingling of code and declarations. Get_Lock() is being called after a line of code (I suspect), which introduces the declaration of oldIrql.
If it is the case that the lock is obtained and released in the same scope always a possible fix (hack) would be to declare KIRQL oldIrql; at the top of the scope where Get_Lock() and Release_Lock() is called, and remove the declaration from Get_Lock().
A tidier solution would be to eliminate the macros and introduce a new struct that defines a lock. For example:
typedef struct _lock
{
#ifdef WIN32
UCHAR oldIrql;
PKSPIN_LOCK sem;
#else
#endif
} lock;
lock* lock_new()
{
lock* result = malloc(sizeof(lock));
/* Perform OS dependent initialisation. */
#ifdef WIN32
#else
#endif
return result;
}
void lock_delete(lock* aLock)
{
/* Perform OS dependent tidy tasks. */
#ifdef WIN32
#else
#endif
free(aLock);
}
void lock_obtain(lock* aLock)
{
/* OS dependent acquire. */
#ifdef WIN32
KeAcquireSpinLock(&aLock->sem, &aLock->oldIrql);
#else
#endif
}
void lock_release(lock* aLock)
{
/* OS dependent release. */
#ifdef WIN32
KeReleaseSpinLock(&aLock->sem, aLock->oldIrql);
#else
#endif
}
I also suspect the reason posted by hmjd. But, in my opinion, the solution can be as follows:
#define Get_Lock(lock) { KIRQL oldIrql; KeAcquireSpinLock(&(lock),&oldIrql);
#define Release_Lock(sync) KeReleaseSpinLock(&(sync),oldIrql) }
But, you need to ensure that Get_Lock & Release_Lock is in same scope which anyway you would be ensuring as per your comments.
The idea is mostly same as that of pthread_cleanup_push & pthread_cleanup_pop. You can refer to the same also.