Windows DLL 与Linux SO库导出符号比较

Windows DLL或者Linux SO库中定义的函数分为内部函数和导出函数,导出的函数供其它程序模块调用。

在DLL中,在导出函数声明时,在函数前面加上_declspec(dllexport)关键字即可导出函数。

在SO中,也有类似的控制参数: -fvisibility=default|internal|hidden|protected

 

需要了解的是,在Linux下,源文件中的所有函数都有一个默认的visibility属性为public,在编译命令中加入-fvisibility=hidden参数,会将所有默认的public的属性变为hidden。此时,如果对函数设置__attribute__ ((visibility("default")))参数,使特定的函数仍然按默认的public属性处理,则-fvisibility=hidden参数不会对该函数起作用。

所以,设置了-fvisibility=hidden参数之后,只有设置了__attribute__ ((visibility("default")))的函数才是对外可见的,如此则效果等同于Visual Studio下的__declspec(dllexport)定义。

下面看一个例子:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
extern int test (int i);
__attribute ((visibility("default"))) int test2 (int i)
{
    test(i);
    printf("this is test2/n");
}
int test3 (int i)
{
    printf("this is test 3/n");
}

此时调用以下命令编译:

gcc -shared -o test.so -fvisibility=hidden test.c

可以获得test.so文件,用以下命令查看so文件属性:

readelf -s test.so

得到以下结果:

Symbol table '.dynsym' contains 12 entries:
  Num:    Value  Size Type    Bind  Vis      Ndx Name
    0: 00000000    0 NOTYPE  LOCAL  DEFAULT  UND 
    1: 00000000    0 NOTYPE  WEAK  DEFAULT  UND __gmon_start__
    2: 00000000    0 NOTYPE  WEAK  DEFAULT  UND _Jv_RegisterClasses
    3: 00000000    0 NOTYPE  GLOBAL DEFAULT  UND test
    4: 00000000    0 FUNC    GLOBAL DEFAULT  UND puts@GLIBC_2.0 (2)
    5: 00000000    0 FUNC    WEAK  DEFAULT  UND __cxa_finalize@GLIBC_2.1.3 (3)
    6: 00002014    0 NOTYPE  GLOBAL DEFAULT  ABS _end
    7: 0000200c    0 NOTYPE  GLOBAL DEFAULT  ABS _edata
    8: 0000049c    31 FUNC    GLOBAL DEFAULT  12 test2
    9: 0000200c    0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
    10: 00000380    0 FUNC    GLOBAL DEFAULT  10 _init
    11: 00000508    0 FUNC    GLOBAL DEFAULT  13 _fini
Symbol table '.symtab' contains 56 entries:
  Num:    Value  Size Type    Bind  Vis      Ndx Name
    0: 00000000    0 NOTYPE  LOCAL  DEFAULT  UND 
    1: 000000f4    0 SECTION LOCAL  DEFAULT    1 
    2: 00000118    0 SECTION LOCAL  DEFAULT    2 
    3: 0000015c    0 SECTION LOCAL  DEFAULT    3 
    4: 00000198    0 SECTION LOCAL  DEFAULT    4 
    5: 00000258    0 SECTION LOCAL  DEFAULT    5 
    6: 000002e0    0 SECTION LOCAL  DEFAULT    6 
    7: 000002f8    0 SECTION LOCAL  DEFAULT    7 
    8: 00000328    0 SECTION LOCAL  DEFAULT    8 
    9: 00000370    0 SECTION LOCAL  DEFAULT    9 
    10: 00000380    0 SECTION LOCAL  DEFAULT  10 
    11: 000003b0    0 SECTION LOCAL  DEFAULT  11 
    12: 000003e0    0 SECTION LOCAL  DEFAULT  12 
    13: 00000508    0 SECTION LOCAL  DEFAULT  13 
    14: 00000524    0 SECTION LOCAL  DEFAULT  14 
    15: 00000544    0 SECTION LOCAL  DEFAULT  15 
    16: 00001f04    0 SECTION LOCAL  DEFAULT  16 
    17: 00001f0c    0 SECTION LOCAL  DEFAULT  17 
    18: 00001f14    0 SECTION LOCAL  DEFAULT  18 
    19: 00001f18    0 SECTION LOCAL  DEFAULT  19 
    20: 00001fe8    0 SECTION LOCAL  DEFAULT  20 
    21: 00001ff4    0 SECTION LOCAL  DEFAULT  21 
    22: 00002008    0 SECTION LOCAL  DEFAULT  22 
    23: 0000200c    0 SECTION LOCAL  DEFAULT  23 
    24: 00000000    0 SECTION LOCAL  DEFAULT  24 
    25: 00000000    0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    26: 00001f04    0 OBJECT  LOCAL  DEFAULT  16 __CTOR_LIST__
    27: 00001f0c    0 OBJECT  LOCAL  DEFAULT  17 __DTOR_LIST__
    28: 00001f14    0 OBJECT  LOCAL  DEFAULT  18 __JCR_LIST__
    29: 000003e0    0 FUNC    LOCAL  DEFAULT  12 __do_global_dtors_aux
    30: 0000200c    1 OBJECT  LOCAL  DEFAULT  23 completed.7021
    31: 00002010    4 OBJECT  LOCAL  DEFAULT  23 dtor_idx.7023
    32: 00000460    0 FUNC    LOCAL  DEFAULT  12 frame_dummy
    33: 00000000    0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    34: 00001f08    0 OBJECT  LOCAL  DEFAULT  16 __CTOR_END__
    35: 00000544    0 OBJECT  LOCAL  DEFAULT  15 __FRAME_END__
    36: 00001f14    0 OBJECT  LOCAL  DEFAULT  18 __JCR_END__
    37: 000004d0    0 FUNC    LOCAL  DEFAULT  12 __do_global_ctors_aux
    38: 00000000    0 FILE    LOCAL  DEFAULT  ABS test.c
    39: 00001ff4    0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
    40: 00002008    0 OBJECT  LOCAL  HIDDEN  22 __dso_handle
    41: 00001f10    0 OBJECT  LOCAL  HIDDEN  17 __DTOR_END__
    42: 000004bb    20 FUNC    LOCAL  HIDDEN  12 test3
    43: 00000497    0 FUNC    LOCAL  HIDDEN  12 __i686.get_pc_thunk.bx
    44: 00001f18    0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
    45: 00000000    0 NOTYPE  WEAK  DEFAULT  UND __gmon_start__
    46: 00000000    0 NOTYPE  WEAK  DEFAULT  UND _Jv_RegisterClasses
    47: 00000508    0 FUNC    GLOBAL DEFAULT  13 _fini
    48: 0000049c    31 FUNC    GLOBAL DEFAULT  12 test2
    49: 0000200c    0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
    50: 00000000    0 NOTYPE  GLOBAL DEFAULT  UND test
    51: 00002014    0 NOTYPE  GLOBAL DEFAULT  ABS _end
    52: 00000000    0 FUNC    GLOBAL DEFAULT  UND puts@@GLIBC_2.0
    53: 0000200c    0 NOTYPE  GLOBAL DEFAULT  ABS _edata
    54: 00000000    0 FUNC    WEAK  DEFAULT  UND __cxa_finalize@@GLIBC_2.1
    55: 00000380    0 FUNC    GLOBAL DEFAULT  10 _init

可以看出,so文件中包含test2()和test3()这两个函数,并且test2()的属性为default(即可见),而test3()的属性则为hidden(不可见)。

参考博客:

https://www.linuxidc.com/Linux/2013-04/82653.htm

如下这段定义,就是一个跨平台的库,同时定义了windows dll和linux so库下导出函数的方法:

#ifndef ASTRA_DEFINES_H
#define ASTRA_DEFINES_H

#ifdef  __cplusplus
    #define ASTRA_BEGIN_DECLS extern "C" {
    #define ASTRA_END_DECLS   }
#else
    #define ASTRA_BEGIN_DECLS
    #define ASTRA_END_DECLS
#endif

#if defined (_MSC_VER)
    #define ASTRA_EXPORT __declspec(dllexport)
    #define ASTRA_IMPORT __declspec(dllimport)

    #define ASTRA_PUBLIC
    #define ASTRA_LOCAL
    #define ASTRA_CALLBACK __cdecl
#else
    #if __GNUC__ >= 4 || defined (__clang__)
        #define ASTRA_PUBLIC __attribute__ ((visibility ("default")))
        #define ASTRA_LOCAL  __attribute__ ((visibility ("hidden")))

        #define ASTRA_EXPORT ASTRA_PUBLIC
        #define ASTRA_IMPORT
        #if defined(__x86_64__) || defined(__ANDROID__)
            #define ASTRA_CALLBACK
        #else
            #define ASTRA_CALLBACK __attribute__ ((__cdecl__))
        #endif
    #else
        #define ASTRA_PUBLIC
        #define ASTRA_LOCAL
        #define ASTRA_EXPORT
        #define ASTRA_IMPORT
        #define ASTRA_CALLBACK
    #endif
#endif

#ifndef ASTRA_API
    #ifdef ASTRA_BUILD
        #define ASTRA_API ASTRA_PUBLIC ASTRA_EXPORT
    #else
        #define ASTRA_API ASTRA_IMPORT
    #endif
#endif

#ifndef ASTRA_API_EX
    #ifdef ASTRA_BUILD_EX
        #define ASTRA_API_EX ASTRA_EXPORT
    #else
        #define ASTRA_API_EX ASTRA_IMPORT
    #endif
#endif

#endif /* ASTRA_DEFINES_H */
 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值