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

目录

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 */

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: __declspec(dllimport) 是一个 Microsoft Visual C++ 扩展关键字,用于在动态链接库中导入函数或数据。它可以用于在编译时指定动态链接库中的函数或数据,以便在运行时使用。 ### 回答2: __declspec(dllimport)是用于在C++中声明导入动态链接库中函数和变量的关键字。在Windows平台上,动态链接库(Dynamic Link Library,简称DLL)是一种将可执行代码和数据封装在一起的文件格式,允许多个程序共享这些代码和数据。使用__declspec(dllimport)关键字可以使程序在编译阶段就知道这些函数和变量是从动态链接库中导入的。 在C++程序中,如果我们需要使用动态链接库中的函数或变量,需要先通过__declspec(dllimport)对这些函数或变量进行声明,然后再进行调用或使用。声明方式如下: __declspec(dllimport) returnType functionName( parameter list ); 其中,returnType表示函数返回值的类型,functionName表示函数名,parameter list表示函数的参数列表。 对于变量的声明,格式如下: __declspec(dllimport) dataType variableName; dataType表示变量的类型,variableName表示变量名。 通过这种方式,程序在编译时就会知道这些函数和变量是从外部导入的,可以正确引用和使用。 总结来说,__declspec(dllimport)关键字主要用于在C++中声明导入动态链接库中函数和变量。它在程序编译阶段就告诉编译器这些函数和变量是从其他地方导入的,使得程序可以正确引用和使用这些导入的函数和变量。 ### 回答3: __declspec(dllimport) 是一个用于 C/C++ 编程语言的 Microsoft 扩展,用于指定在编译时导入 DLL 中定义的函数或变量。该关键字的作用是告诉编译器和链接器,在当前的源文件中,所使用的某个函数或变量是在外部的 DLL 文件中定义的,需要从 DLL 文件中导入。 在使用 __declspec(dllimport) 关键字时,需要先使用 __declspec(dllexport) 关键字在 DLL 文件中导出相应的函数或变量。然后在其他的源文件中,通过 __declspec(dllimport) 关键字来声明相应的函数或变量,告诉编译器和链接器需要从 DLL 文件中导入该函数或变量的定义。 __declspec(dllimport) 关键字可以在函数或变量的声明前使用,以指定导入的函数或变量的属性。它告诉编译器该函数或变量是在其他 DLL 文件中定义的,并且编译器在编译时会将其处理为外部引用。这样,程序在运行时就可以动态地加载和使用 DLL 文件中的函数或变量。 总结来说,__declspec(dllimport) 是一个 Microsoft 扩展,用于在 C/C++ 编程语言中指定从 DLL 文件中导入函数或变量的关键字。通过使用这个关键字,可以告诉编译器和链接器在编译时将引用的函数或变量作为外部引用,并在运行时动态地加载和使用 DLL 文件中的相应函数或变量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值