unknown type name '__declspec' 和 unknown type name 'class' 错误

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lc250123/article/details/81985336

目录

unknown type name '__declspec'

unknown type name 'class'

extern "C" 的作用


unknown type name '__declspec'

最近搞一个跨平台项目,在 Linux 下使用别人的库时发现别人头文件是这么写的:

#if defined SAPCLASSBASIC
	#define SAPCLASSBASIC_VAR	__declspec(dllexport)
	#define SAPCLASSBASIC_CLASS	__declspec(dllexport)
#else
	#define SAPCLASSBASIC_VAR	__declspec(dllimport)
	#define SAPCLASSBASIC_CLASS	__declspec(dllimport)
#endif

编译时出现很多错误,其中有:unknown type name '__declspec'

其实,__declspec 是 windows 专属,在 Linux 下,如果使用 GCC 就不能这样写,写法如下:

#if defined(_MSC_VER)
    //  Microsoft 
    #define EXPORT __declspec(dllexport)
    #define IMPORT __declspec(dllimport)
#elif defined(__GNUC__)
    //  GCC
    #define EXPORT __attribute__((visibility("default")))
    #define IMPORT
#else
    //  do nothing and hope for the best?
    #define EXPORT
    #define IMPORT
    #pragma warning Unknown dynamic link import/export semantics.
#endif

__declspec(dllexport) 替换成 __attribute__((visibility("default"))) , __declspec(dllimport) 替换成 空 即可。

下面是比较全面的写法和用法:

#if defined _WIN32 || defined __CYGWIN__
  #ifdef BUILDING_DLL
    #ifdef __GNUC__
      #define DLL_PUBLIC __attribute__ ((dllexport))
    #else
      #define DLL_PUBLIC __declspec(dllexport) // Note: actually gcc seems to also supports this syntax.
    #endif
  #else
    #ifdef __GNUC__
      #define DLL_PUBLIC __attribute__ ((dllimport))
    #else
      #define DLL_PUBLIC __declspec(dllimport) // Note: actually gcc seems to also supports this syntax.
    #endif
  #endif
  #define DLL_LOCAL
#else
  #if __GNUC__ >= 4
    #define DLL_PUBLIC __attribute__ ((visibility ("default")))
    #define DLL_LOCAL  __attribute__ ((visibility ("hidden")))
  #else
    #define DLL_PUBLIC
    #define DLL_LOCAL
  #endif
#endif

extern "C" DLL_PUBLIC void function(int a);
class DLL_PUBLIC SomeClass
{
   int c;
   DLL_LOCAL void privateMethod();  // Only for use within this DSO
public:
   Person(int _c) : c(_c) { }
   static void foo(int a);
};

详细见:http://gcc.gnu.org/wiki/Visibility


unknown type name 'class'

然后 __declspec 的错误没有了,接着又发生了 unknown type name 'class' 错误,这是因为我的编译环境自动使用的是 gcc 来编译的,程序文件都是 .c 结尾的,我将 .c 改为 .cpp 即可。

原因:当 c 使用 c++ 头文件时,C 文件 include 了带有 C++ 关键字的头文件,如 class 等。因此,包含 C++ 关键字的头文件被 C 编译器所编译,而不是用 C++ 编译器编译,而 C 编译器无法识别 C++ 的关键字,所以报错。

解决方法:

1、最好不要在 C 文件中包含 C++ 的头文件,建议将 .c 改成 .cpp

2、在所有使用 C++ 方法的地方加上:#ifdef __cplusplus,如:

        #ifdef __cplusplus
            class A{

            };
        #endif

注意:如果 c++ 文件中使用了 extern "C" ,我们要另外声明,因为 C 中是没有 extern "C" 的:

//C++头文件 cppExample.h 
#ifndef CPP_EXAMPLE_H 
#define CPP_EXAMPLE_H 
    extern "C" int add( int x, int y ); 
#endif 


/* C实现文件 cFile.c */
extern int add( int x, int y ); 
int main( int argc, char* argv[] ) 
{  
    add( 2, 0 );  
    return 0; 
}

extern "C" 的作用

被 extern "C" 修饰的变量和函数是按照 C 语言方式编译和链接的,关于 c 和 c++ 的编译链接的不同之处暂且不做讨论。

在标准 C 的头文件中,经常看到如下版本:

#ifndef __FILE_H /*防止该头文件被重复引用*/ 
#define __FILE_H 

#ifdef __cplusplus //__cplusplus是cpp中自定义的一个宏 
    extern "C" { //告诉编译器,这部分代码按C语言的格式进行编译,而不是C++的 
#endif 

    /**** some declaration or so *****/ 

#ifdef __cplusplus 
    } 
#endif 

#endif /* __FILE_H */

所以,我们在写 C 文件时,考虑到使用者有可能是 C++ 用户,最好要加上这样的标注。还有如下应用场合:

当我们使用 C++ 编程,需要引用 C 库和其头文件,那么我们在 C++ 文件中应该这么写:

    #ifndef __CPP_FILE_H /* cpp 头文件 */ 
    #define __CPP_FILE_H 

    extern "C"
    {
        #include "cExample.h"
    }

    #endif /* __CPP_FILE_H */

猜你喜欢

转载自blog.csdn.net/lc250123/article/details/81985336