简体   繁体   中英

Compile as C code in Visual Studio 2010

I am writing some C code to interface with a piece of hardware. This hardware has built-in API functions, which are defined in a header file, enclosed in an extern "C" block. For some reason, I cannot get the program to compile when I select "compile as C code" in the property sheets. Even stranger, I can get it to give no errors when I "compile as C++", don't change any code, then change it back to "compile as C". What is going on? The only two files I have are main.c, header_file.h, and a defines_file.h (which is #include d in header_file.h).

I wrote a very simple program to illustrate what is happening:

#include "header_file.h"

int main(){
  return 0;
}

To give some more detail, the error I am getting is coming from the header file, which looks something like:

#ifdef __cplusplus
extern "C" {
#endif

#include defines_file.h

FUNC_API(int) Function(Type1 var1, Enum2 var2, Type3 var3, void* ptr=0);

#ifdef __cplusplus
}
#endif

The defines_file.h looks like:

enum Enum2{
//enumerator list
};

The errors are:

1>c:\header_file\include\header_file.h(78): error C2146: syntax error : missing ')' before identifier 'var2'
1>c:\header_file\include\header_file.h(78): error C2081: 'Enum2' : name in formal parameter list illegal
1>c:\header_file\include\header_file.h(78): error C2061: syntax error : identifier 'var2'
1>c:\header_file\include\header_file.h(78): error C2059: syntax error : ';'
1>c:\header_file\include\header_file.h(78): error C2059: syntax error : ','
1>c:\header_file\include\header_file.h(78): error C2059: syntax error : ')'

It seems like it's thinking that Enum2 is a variable name of Type1 . It's as though I'm missing the Enum2 definition, but I'm not - it's defined in defines_file.h. One thing I did notice is that Enum2 is not defined inside an "extern C" block. Is that a problem? I don't want to change the header files because I didn't write them. (I'm still not 100% sure how "extern C" works.)

The interface declared extern "C" must itself be valid C; so the interface:

  • May not be a class member
  • May not be overloaded
  • May not involve class types
  • May not have optional arguments
  • Must be syntactically valid as C code.

You can use POD structs so long as they themselves are declared extern "C" in C++ compilation. In C, unlike C++ struct, enum and union tags are not on their own type names, so must be explicitly qualified, or a typedef alias defined.

Note that the following:

#if defined __cplusplus
extern "C"
{
#endif
    // Declarations must be valid C syntax
    int function() ;
#if defined __cplusplus
}
#endif

Resolves to:

extern "C"
{
    // Declarations must be valid C syntax
    int function() ;  
}

in C++, and just:

    // Declarations must be valid C syntax
    int function() ;  

in C

The important point is that when compiled as C code, nothing C++ specific may be included.

The extern "C" is C++ syntax to switch of all symbol name mangling that is necessary to support overloading, class membership, and optional parameters etc. and which is not valid C. It forces the symbol name in C++ compilation to be the same as that in C compilation.

In C you need to define an enum as a type or actually prefix it with the word enum when you use it like a type name.

So either you need to modify the definition

//replace this:
enum Enum2{A,B,C,D};

//with this
typedef enum{A,B,C,D} Enum2;

or you can keep the definition the same and change the function signature to

FUNC_API(int) Function(Type1 var1, enum Enum2 var2, Type3 var3, void* ptr);

The fact of the matter is that C and C++ are two distinct languages and if the header wasn't written with one of the two in mind, then you can just not use it without modifying it.

edit : as @Clifford mentioned, the same goes for struct types.

struct Type1  //this is passed as "struct Type1 pName"
{
    int a,b,c;
};

typedef struct //this is passed as "Type2 pName"
{
    int a,b,c;
}Type2;

//this is passed as either "struct type3 pName" or "type3_t pName"
typedef struct type3
{
    int a,b,c;
}type3_t;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM