4

我正在为我的一个项目构建一个 C++ DLL。我正在尝试标准化定义类的方式。所以不是每次都写:

class __declspec(dllexport) ClassName

我正在构建一个#define宏来简化这个过程:

#define CLASS( cName ) class __declspec(dllexport) cName

但是,当我使用它时,它给了我以下错误:

Error: Expected a ';'

我知道您可以使用#define宏来定义整个类的创建,但它可以只用于定义“类头”吗?

谢谢,

请记住,我正在尝试这样做,因为我们要处理数百个类,所以这些“自动化”将是最有帮助的 :)

编辑:

例子:

#define CLASS( nClass ) class __declspec(dllexport) nClass

CLASS( APTest )
{                        // Here is the error of missing ';'
public:
    APTest();
};
4

2 回答 2

15

不要这样做。

C++ 已经标准化了!

如果您希望其他人阅读您的代码,那么只需使用传统的 C++ 编写它,而不是一些看起来不同的家常方言。习惯正确的 C++ 语法,它将更容易阅读其他人的 C++ 代码。

有意义的一件事是简化__declspec部分,您可以这样做:

#ifdef _WIN32
#define DLLEXPORT __declspec(dllexport) 
#else
#define DLLEXPORT
#endif

class DLLEXPORT APTest
{
    // ...
};

写作并没有让你的生活变得更简单,CLASS( APTest )反而让别人更难理解。拒绝吧。

于 2013-05-21T13:34:21.753 回答
1

有比@Wakely 更好的方法。像这样做:

#ifdef MYLIB_DLL

#ifndef MYLIB_IFACE
#ifdef MYLIB_IFACE_EXPORT
#define MYLIB_IFACE _declspec( dllexport )
#else  // !MYLIB_IFACE_EXPORT
#define MYLIB_IFACE _declspec( dllimport )
#endif // !MYLIB_IFACE_EXPORT
#endif // !MYLIB_IFACE

#else  // !MYLIB_DLL

#ifndef MYLIB_IFACE
#define MYLIB_IFACE
#endif // !MYLIB_IFACE

将这样的块放在 dll 中每个文件使用的标头中,以及 dll 的公共标头中。

应该从您的 dll 中导出的每个符号都被标记如下:

class MYLIB_IFACE MyClass 
{
};

void MYLIB_IFACE myFunc();

然后在您的 dll 中的每个 .cpp 文件中,第一行应该是:

#define MYLIB_IFACE_EXPORT

如果您这样做,那么它将在不使用 dllexport/dllimport 的 POSIX 系统上构建得很好。要构建 lib 的 dll 版本,您需要定义 MYLIB_DLL。(您可以在编译器的标志中执行此操作,以便可以从您的构建系统控制它)

要构建 lib 的静态版本,请不要定义 MYLIB_DLL。

@更新:

您可以扩展它以支持 GCC 可见性,如下所示:

#ifdef WIN32
#define KX_SYMBOL_EXPORT _declspec( dllexport )
#define KX_SYMBOL_IMPORT _declspec( dllimport )
#else // GCC
#define KX_SYMBOL_EXPORT __attribute__(( visibility ("default")))
#define KX_SYMBOL_IMPORT 
#endif

#ifdef KX_DLL

#ifndef KX_IFACE
#ifdef KX_IFACE_EXPORT
#define KX_IFACE KX_SYMBOL_EXPORT
#else  // !KX_IFACE_EXPORT
#define KX_IFACE KX_SYMBOL_IMPORT
#endif // !KX_IFACE_EXPORT
#endif // !KX_IFACE

#else  // !KX_DLL

#ifndef KX_IFACE
#define KX_IFACE
#endif // !KX_IFACE

#endif // !KX_DLL

为简单起见,我在第一个示例中删除了 GCC 位。但这就是真正做到这一点的方式。@Wakely 是对的。

于 2013-05-21T15:22:25.630 回答