Apa yang harus saya lakukan jika saya memiliki dua pustaka yang menyediakan fungsi dengan nama yang setara?
vorbis_...
. sf_...
, sdl_...
). Ini pada dasarnya adalah apa yang C ++ lakukan pada nama simbol untuk fungsi spasi nama.
Apa yang harus saya lakukan jika saya memiliki dua pustaka yang menyediakan fungsi dengan nama yang setara?
vorbis_...
. sf_...
, sdl_...
). Ini pada dasarnya adalah apa yang C ++ lakukan pada nama simbol untuk fungsi spasi nama.
Jawaban:
Apropos komentar: Dengan "ekspor" maksud saya untuk membuat terlihat modul yang menghubungkan ke perpustakaan --- setara dengan extern
kata kunci di ruang lingkup file. Bagaimana ini dikontrol tergantung pada OS dan linker. Dan itu adalah sesuatu yang harus selalu saya cari.
Dimungkinkan untuk mengganti nama simbol dalam file objek menggunakan objcopy --redefine-sym old=new file
(lihat man objcopy).
Kemudian panggil saja fungsi menggunakan nama barunya dan tautkan dengan file objek baru.
Di bawah Windows, Anda dapat menggunakan LoadLibrary () untuk memuat salah satu pustaka tersebut ke dalam memori dan kemudian menggunakan GetProcAddress () untuk mendapatkan alamat setiap fungsi yang Anda perlukan untuk memanggil dan memanggil fungsi melalui penunjuk fungsi.
misalnya
HMODULE lib = LoadLibrary("foo.dll");
void *p = GetProcAddress(lib, "bar");
// cast p to the approriate function pointer type (fp) and call it
(*fp)(arg1, arg2...);
FreeLibrary(lib);
akan mendapatkan alamat dari fungsi bernama bar di foo.dll dan memanggilnya.
Saya tahu sistem Unix mendukung fungsi serupa, tetapi saya tidak dapat memikirkan namanya.
dlopen
dlsym
, dan dlclose
. Namun, enkapsulasi pada Unix mungkin tidak seefektif Windows.
Inilah pemikirannya. Buka salah satu pustaka yang melanggar di editor hex dan ubah semua kemunculan string yang menyinggung ke sesuatu yang lain. Anda kemudian dapat menggunakan nama baru di semua panggilan di masa mendatang.
UPDATE: Saya baru saja melakukannya di akhir ini dan tampaknya berhasil. Tentu saja, saya belum mengujinya secara menyeluruh - ini mungkin tidak lebih dari cara yang sangat baik untuk meledakkan kaki Anda dengan senapan hexedit.
Dengan asumsi Anda menggunakan linux, Anda perlu menambahkan file
#include <dlfcn.h>
Deklarasikan variabel penunjuk fungsi dalam konteks yang tepat, misalnya,
int (*alternative_server_init)(int, char **, char **);
Seperti yang dinyatakan Ferruccio di https://stackoverflow.com/a/678453/1635364 , muat secara eksplisit pustaka yang ingin Anda gunakan dengan menjalankan (pilih bendera favorit Anda)
void* dlhandle;
void* sym;
dlhandle = dlopen("/home/jdoe/src/libwhatnot.so.10", RTLD_NOW|RTLD_LOCAL);
Baca alamat fungsi yang ingin Anda panggil nanti
sym = dlsym(dlhandle, "conflicting_server_init");
menetapkan dan berperan sebagai berikut
alternative_server_init = (int (*)(int, char**, char**))sym;
Panggil dengan cara yang mirip dengan aslinya. Terakhir, bongkar dengan menjalankan
dlclose(dlhandle);
Anda tidak boleh menggunakannya bersama. Jika saya ingat dengan benar, linker mengeluarkan kesalahan dalam kasus seperti itu.
Saya tidak mencoba, tetapi mungkin ada solusinya dlopen()
, dlsym()
dan dlclose()
yang memungkinkan Anda menangani pustaka dinamis secara terprogram. Jika Anda tidak membutuhkan dua fungsi pada saat yang sama, Anda dapat membuka pustaka pertama, menggunakan fungsi pertama dan menutup pustaka pertama sebelum menggunakan pustaka / fungsi kedua.
Jika Anda memiliki file .o di sana, jawaban yang bagus di sini: https://stackoverflow.com/a/6940389/4705766
Ringkasan:
objcopy --prefix-symbols=pre_string test.o
untuk mengganti nama simbol dalam file .o atau
objcopy --redefine-sym old_str=new_str test.o
untuk mengganti nama simbol tertentu dalam file .o.Masalah ini adalah alasan c ++ memiliki ruang nama. Sebenarnya tidak ada solusi hebat di c untuk 2 lib pihak ketiga yang memiliki nama yang sama.
Jika itu adalah objek dinamis, Anda mungkin dapat memuat objek bersama secara eksplisit (LoadLibrary / dlopen / etc) dan memanggilnya dengan cara itu. Bergantian, jika Anda tidak memerlukan kedua lib secara bersamaan dalam kode yang sama, Anda mungkin dapat melakukan sesuatu dengan tautan statis (jika Anda memiliki file .lib / .a).
Tak satu pun dari solusi ini berlaku untuk semua proyek, tentu saja.
Bersumpah? Sejauh yang saya ketahui, tidak banyak yang dapat Anda lakukan jika Anda memiliki dua pustaka yang mengekspos titik tautan dengan nama yang sama dan Anda perlu menautkan keduanya.
Anda harus menulis pustaka pembungkus di sekitar salah satunya. Perpustakaan pembungkus Anda harus mengekspos simbol dengan nama unik, dan tidak mengekspos simbol nama non-unik.
Pilihan Anda yang lain adalah mengganti nama fungsi di file header, dan mengganti nama simbol di arsip objek perpustakaan.
Bagaimanapun, untuk menggunakan keduanya, ini akan menjadi pekerjaan hack.
Pertanyaannya mendekati satu dekade, tetapi ada pencarian baru sepanjang waktu ...
Seperti yang sudah dijawab, objcopy dengan flag --redefine-sym adalah pilihan yang baik di Linux. Lihat, misalnya, https://linux.die.net/man/1/objcopy untuk dokumentasi lengkap. Ini sedikit kikuk karena pada dasarnya Anda menyalin seluruh pustaka sambil membuat perubahan dan setiap pembaruan mengharuskan pekerjaan ini diulang. Tapi setidaknya itu harus berhasil.
Untuk Windows, memuat pustaka secara dinamis adalah solusi dan solusi permanen seperti alternatif dlopen di Linux. Namun baik dlopen () dan LoadLibrary () menambahkan kode tambahan yang dapat dihindari jika satu-satunya masalah adalah nama duplikat. Di sini solusi Windows lebih elegan daripada pendekatan objcopy: Cukup beri tahu linker bahwa simbol di pustaka dikenal dengan nama lain dan gunakan nama itu. Ada beberapa langkah untuk melakukannya. Anda perlu membuat file def dan memberikan terjemahan nama di bagian EKSPOR. Lihat https://msdn.microsoft.com/en-us/library/hyx1zcd3.aspx (VS2015, pada akhirnya akan diganti dengan versi yang lebih baru) atau http://www.digitalmars.com/ctg/ctgDefFiles.html(mungkin lebih permanen) untuk detail sintaks lengkap dari file def. Prosesnya adalah membuat file def untuk salah satu perpustakaan kemudian menggunakan file def ini untuk membuat file lib dan kemudian menautkan dengan file lib itu. (Untuk Windows DLL, file lib hanya digunakan untuk penautan, bukan eksekusi kode.) Lihat Cara membuat file .lib saat memiliki file .dll dan file header untuk proses pembuatan file lib. Di sini satu-satunya perbedaan adalah menambahkan alias.
Untuk Linux dan Windows, ganti nama fungsi di header pustaka yang namanya dialias. Opsi lain yang seharusnya berfungsi adalah, dalam file yang merujuk ke nama baru, #define old_name new_name, #include headers library yang ekspornya sedang dialias, lalu #undef old_name di pemanggil. Jika ada banyak file yang menggunakan pustaka, alternatif yang lebih mudah adalah membuat tajuk atau tajuk yang membungkus definisi, penyertaan, dan undef, lalu gunakan tajuk itu.
Semoga info ini bermanfaat!
Saya tidak pernah menggunakan dlsym, dlopen, dlerror, dlclose, dlvsym, dll., Tapi saya melihat halaman manual, dan ini memberikan contoh membuka libm.so dan mengekstrak fungsi cos. Apakah dlopen melalui proses mencari tabrakan? Jika tidak, OP bisa memuat kedua perpustakaan secara manual dan menetapkan nama baru ke semua fungsi yang disediakan perpustakaannya.