Jika Anda membungkus bagian pribadi Anda dalam ruang nama anonim maka tidak ada std::abs
maupun private_function
dapat dilihat pada tabel simbol:
namespace{
#include<cmath>
float private_function(float f)
{
return std::abs(f);
}
}
extern "C" float public_function(float f)
{
return private_function(f);
}
kompilasi (g++ 4.3.3):
g++ -shared -o libtest.so test.cpp -s
memeriksa:
# nm -DC libtest.so
w _Jv_RegisterClasses
0000200c A __bss_start
w __cxa_finalize
w __gmon_start__
0000200c A _edata
00002014 A _end
000004a8 T _fini
000002f4 T _init
00000445 T public_function
Perlu diketahui bahwa Ulrich Drepper menulis esai tentang (semua?) aspek penulisan pustaka bersama untuk Linux/Unix, yang mencakup kontrol simbol yang diekspor di antara banyak topik lainnya.
Ini sangat berguna untuk memperjelas cara mengekspor hanya fungsi pada daftar putih dari lib bersama.
Penggunaan Anda atas atribut visibilitas default dan -fvisibility=hidden harus ditambah dengan -fvisibility-inlines-hidden.
Anda juga harus melupakan tentang mencoba menyembunyikan ekspor stdlib, lihat bug GCC ini untuk alasannya.
Selain itu, jika Anda memiliki semua simbol publik di header tertentu, Anda dapat membungkusnya dalam #pragma GCC visibility push(default)
dan #pragma GCC visibility pop
daripada menggunakan atribut. Meskipun jika Anda membuat pustaka lintas platform, lihat Mengontrol Simbol yang Diekspor dari Pustaka Bersama untuk teknik menyatukan strategi ekspor Windows DLL dan Linux DSO.
Jadi solusi yang kami miliki untuk saat ini adalah sebagai berikut:
test.cpp
#include <cmath>
#include <vector>
#include <typeinfo>
struct private_struct
{
float f;
};
float private_function(float f)
{
return std::abs(f);
}
void other_private_function()
{
std::vector<private_struct> f(1);
}
extern "C" void __attribute__ ((visibility ("default"))) public_function2()
{
other_private_function();
}
extern "C" float __attribute__ ((visibility ("default"))) public_function1(float f)
{
return private_function(f);
}
ekspor.versi
LIBTEST
{
global:
public*;
local:
*;
};
dikompilasi dengan
g++ -shared test.cpp -o libtest.so -fvisibility=hidden -fvisibility-inlines-hidden -s -Wl,--version-script=exports.version
memberi
00000000 A LIBTEST
w _Jv_RegisterClasses
U _Unwind_Resume
U std::__throw_bad_alloc()
U operator delete(void*)
U operator new(unsigned int)
w __cxa_finalize
w __gmon_start__
U __gxx_personality_v0
000005db T public_function1
00000676 T public_function2
Yang cukup dekat dengan apa yang kita cari. Namun ada beberapa gotcha:
- Kita harus memastikan bahwa kita tidak menggunakan awalan "diekspor" (dalam contoh sederhana ini "publik", tetapi jelas sesuatu yang lebih berguna dalam kasus kita) dalam kode internal.
- Banyak nama simbol masih berakhir di tabel string, yang tampaknya turun ke RTTI, -fno-rtti membuatnya hilang dalam pengujian sederhana saya, tetapi merupakan solusi yang agak nuklir.
Saya senang menerima solusi yang lebih baik dari siapa pun!