欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

c接口跨平台头文件模板

程序员文章站 2022-04-27 08:16:48
...

源码模板

#ifndef XXX_H
#define XXX_H

#ifdef _WIN32
    #if defined(XXX_STATIC)
        #define DLL_API
    #else
        #if defined(DLL_EXPORTS)
            #define DLL_API __declspec(dllexport)
        #else
            #define DLL_API __declspec(dllimport)
        #endif // DLL_EXPORTS 
    #endif // XXX_STATIC
    #define CALLSPEC __stdcall
#else
    #if __GNUC__ >= 4
        #define DLL_API __attribute__((visibility("default")))
    #else
        #define DLL_API
    #endif
    #define CALLSPEC
#endif // _WIN32

//--------------------data-struct------------------------------
#ifdef __cplusplus

#define ENUM(x) \
enum x

#define STRUCT(x) \
struct x

#else

#define ENUM(x) \
typedef enum x x; \
enum x

#define STRUCT(x) \
typedef struct x x; \
struct x

#endif

#ifdef __GNUC__
#define GNUC_ALIGN(n) __attribute__((align(n)))
#endif

ENUM(x) {

};

#ifdef _WIN32
#pragma pack(push)
#pragma pack(n)
#endif

STRUCT(x) {

} GNUC_ALIGN(n);

#ifdef _WIN32
#pragma pack(pop)
#endif

//===============================================================

//---------------------function----------------------------------
#ifdef __cplusplus
extern "C" {
#endif

DLL_API void CALLSPEC foobar();

#ifdef __cplusplus
}
#endif
//===============================================================

#endif // XXX_H

说明

防止头文件重复包含

msvc下可以使用#pragma once这样的方式,但为了跨编译器,最好习惯如下通用形式

#ifndef XXX_H
#define XXX_H
#endif

Windows下导出dll说明

#if defined(DLL_EXPORTS)
    #define DLL_API __declspec(dllexport)
#else
    #define DLL_API __declspec(dllimport)
#endif // DLL_EXPORTS

Windows下如果需要使用静态库,需要添加#define XXX_STATIC

调用约定

#define CALLSPEC __stdcall

Windows API接口一般使用__stdcall调用约定(default is __cdecl)
__stdcall__cdecl参数都是从右到左入栈,不同的是__stdcall由函数自身管理栈,__cdecl由调用者管理栈。
此为msvc x86__stdcall生成的dll符号名会形如[email protected],需要加.def文件强制命名。

def文件格式如下

LIBRARY "xxx"

EXPORTS

SdkInit         @1
SdkCleanup      @2

msvc可以使用dumpbin命令查看dll的导出符号,使用lib命令生成xxx.lib动态链接库导入文件

dumpbin /exports xxx.dll
lib   /def:xxx.def  /mechine:ARM|ARM64|EBC|X64|X86 /out:xxx.lib

更详细的命令说明请直接在cmd下查看命令帮助

typedef struct

#define ENUM(x)
#define STRUCT(x)

宏定义ENUMSTRUCT的目的是给x加上typedef定义类型,使得C能够和C++一样能够直接使用x,而不是struct x这样繁琐的方式。

字节对齐

msvc和gnuc字节对齐的语法不同,msvc使用#pragma pack(n),gnuc使用__attribute__((align(n)))

#ifdef __GNUC__
#define GNUC_ALIGN(n) __attribute__((align(n)))
#endif

#ifdef _WIN32
#pragma pack(push)
#pragma pack(n)
#endif

STRUCT(x){

} GNUC_ALIGN(n);

#ifdef _WIN32
#pragma pack(pop)
#endif