在没有明确导出指令的情况下构建共享库时,GCC 如何决定导出哪些函数?

问题描述 投票:0回答:1

我试图了解 GCC 在构建共享库(

.so
.dll
)时如何决定导出哪些函数,而没有提供任何明确的导出指令(例如
.def
文件或
__attribute__((visibility("default")))
注释)。

考虑 Node.js 本机插件的以下 C 代码:

#include <assert.h>
#include <node/node_api.h>

napi_value Method(napi_env env, napi_callback_info info) {
   napi_status status;
   napi_value world;
   status = napi_create_string_utf8(env, "world", NAPI_AUTO_LENGTH, &world);
   assert(status == napi_ok);
   return world;
}

#define DECLARE_NAPI_METHOD(name, func) \
   { name, 0, func, 0, 0, 0, napi_default, 0 }

napi_value napi_register_module_v1(napi_env env, napi_value exports) {
   napi_status status;
   napi_property_descriptor desc = DECLARE_NAPI_METHOD("hello", Method);
   status = napi_define_properties(env, exports, 1, &desc);
   assert(status == napi_ok);
   return exports;
}

使用 GCC 编译此代码时(例如,

gcc -shared -fPIC hello.c -lnode -o hello.node
),会导出
napi_register_module_v1
函数,但不会导出
Method
函数。我听说 GCC 默认导出所有内容。但在这种情况下却不然,为什么?

$ cat hello.def
;
; Definition file of hello.node
; Automatic generated by gendef
; written by Kai Tietz 2008
;
LIBRARY "hello.node"
EXPORTS
Method
napi_register_module_v1

我的问题是:在这种情况下,GCC 使用什么启发法或约定来决定导出

napi_register_module_v1
而不是
Method

windows gcc mingw-w64
1个回答
0
投票

gcc 的默认行为是导出所有未声明为静态的符号。可以使用命令行参数 -fvisibility 更改此行为。将其设置为“隐藏”会使默认情况下不导出所有符号。除了隐藏之外,还有其他几种可能性。

 -fvisibility=[default|internal|hidden|protected] 

在代码中,可以使用visibility属性设置符号的可见性:

void __attribute__((visibility("default"))) myFunction()
{
    // ...
}

此外,可以使用链接器脚本来指定导出哪些函数,但在这里描述它是如何工作的有点偏离主题。

鉴于此信息,我没有理由明白为什么 Method() 没有被导出。

您可以使用 readelf 程序确认正在导出哪些函数。下面将列出lib.so中导出的函数。确认所有地方的“Method”符号拼写正确。

readelf -s lib.so
© www.soinside.com 2019 - 2024. All rights reserved.