كيفية استخدام 2 c libs التي تصدر نفس أسماء الوظائف [مكررة

StackOverflow https://stackoverflow.com/questions/681200

  •  22-08-2019
  •  | 
  •  

سؤال

تكرار السؤال التالي: C تعارض الوظيفة


مرحبًا ، في مشروعي الحالي ، يجب أن أستخدم نوعًا من الواجهة. يتم تقديم أسماء الوظائف بواسطة هذه الواجهة ، ما تفعله هذه الوظائف هو اختيار المطورين. بقدر ما أستطيع أن أقول يجب أن يستخدم المشروع هذه الوظائف وعندما يتعلق الأمر بتجميعك تختار lib ومعه الوظيفة. ما أحاول القيام به هو استخدام lib موجود و lib الخاص بي في نفس الوقت عن طريق لف الآخر والاتصال به في وظائف mein:

eShoneLib:

int function1 (int a) {
// do something
}

ميلب:

int function1 (int a) {
//my code here
    otherlib::function1(a);
}

المشكلة هي أنه ليس لدي إمكانية الوصول إلى LIB الآخر ولا يحتوي LIB الآخر على أي مساحات أسماء. لقد حاولت بالفعل

namespace old {
    #include "otherlib.h"
}

ثم اتصل بالوظيفة القديمة بواسطة Old :: Function1 في وظيفتي. هذا يعمل طالما أنه ملف رأس فقط. يصدر LIB رمزها إلى الفضاء العالمي. أيضا شيء مثل

namespace new {
    function1 (int a) {
        ::function1(a);
    }
}

لم ينجح. أخيرًا وليس آخرًا ، جربت IFDEFs وأحدد المقترحة المقترحة هنا

لكنني لم أكن ناجحًا.

هل توجد أية أفكار لحل هذا؟ شكرا مقدما.

تحرير: ليس لدي إمكانية الوصول إلى lib القديم ولا المشروع يجب استخدام كلا libs في.

EDIT2: على الأقل lib القديم هو ثابت

هل كانت مفيدة؟

المحلول

مساحات الأسماء في C تم حلها باستخدام بادئات أسماء المكتبة مثل:

libfoo -> foo_function1
libbar -> bar_function1

هذه البادئات هي مساحات الأسماء الفعلية. لذلك إذا كتبت libbar

int bar_function1(int a) {
     function1(a);
}

هذه هي الطريقة لحل المشكلات.

C له مساحات أسماء --- يطلقون فقط على البادئات ؛)

خيار آخر هو القيام بالعديد من الحيل القذرة مع تحميل ديناميكي للمكتبات مثل:

h1=dlopen("libfoo.so")
foo_function1=dlsym(h1,"function1")

h2=dlopen("libbar.so")
bar_function1=dlsym(h2,"function1")

نصائح أخرى

يبدو كما لو أن LIB الآخر هو C والرمز الخاص بك هو C ++. يمكنك أن تواجه مشكلة في التشويش (C ++ Compilers MANCED الرموز - أضف أشياء إضافية في اسم الرمز تقوم بتمييز الحمولة الزائدة وما شابه ذلك).

إذا كانت المكتبة نقية ، فيمكنك المحاولة:

extern "C" { // disable mangling of symbol names in the block
#include "otherlib.h"
}

namespace new_lib { // new is a reserved word
   int function1( int a ) {
      ::function1(a);
   }
}

لم أحاول ذلك. فكر أيضًا في توفير رسائل الخطأ التي تحصل عليها.

هناك خيار آخر هو (إذا كانت المكتبة ديناميكية) قم بتحميل LIB ديناميكيًا واتصال الوظيفة. في Linux (لا أعرف عن Windows) ، يمكنك استخدام Dlopen لفتح المكتبة ، DLSYM للحصول على الرمز والاتصال به:

// off the top of my head, not tried:
int function1( int a )
{
   int (*f)(int); // define the function pointer
   void * handle = dlopen( "library.so" );
   f = dlsym( handle, "function1" );
   f( a ); // calls function1(a) in the dynamic library
}

في هذه الحالة ، نظرًا لأنك لا تربط المكتبة ، فلن تحصل على تعارض رمزي ، ولكن مرة أخرى ، فهي صالحة فقط للمكتبات الديناميكية وهي مرهقة للغاية للاستخدام المنتظم.

تحديث

إذا لم يستخدم المستخدمون "otherlib" مباشرة (لن يتضمنوا رؤوسهم) وسيكونون C ++ فقط ، فقد يكون النهج الأول ممكنًا (حتى لو كان أمرًا مروعًا للقراءة):

// newlib.h
namespace hideout {
   int f( int a );
}
using namespace hideout; // usually I would not put this on the header

// newlib.cpp
extern "C" { // if otherlib is C, else remove this line
#include "otherlib.h"
}
namespace hideout {
   int f( int a ) { return ::f( a*2 ); }
}

// main.cpp
#include "newlib.h"
int main()
{
   std::cout << f( 5 ) << std::endl;
}

كيف يعمل؟ سوف يرى رمز المستخدم فقط إعلان الوظيفة 1 (في المثال F ()) لأنه لا يشمل otherlib.h. داخل وحدة التجميع الخاصة بك ، ترى الإعلانين ولكنك تميز من خلال استخدام مساحة الاسم. لا يزعجك البيان باستخدام الرأس في الرأس لأنك مؤهل تمامًا في حزب الشعب الباكستاني. المستخدم Main.cpp سيشمل رأسك فقط ، لذلك سوف يرى المترجم فقط مخبأ :: f, ، وسوف نراها في أي مكان بسبب البيان باستخدام. لن يواجه الرابط مشكلة لأن رمز C ++ يتم تشويهه لتحديد مساحة الاسم الحقيقية:

// g++ 4.0 in macosx:
00002dbe T __ZN7hideout9function1Ei // namespace hideout, function1 takes int, returns int
00002db0 T _function1

إذا كان رمز المستخدم سيتضمن كل من رأسك و otherlib.h ثم سيتعين عليه تأهيل الوظيفة التي تريد الاتصال بها.

إذا كنت يائسة حقًا ، فيمكنك كتابة مكتبة غلاف تستخدم مساحات الأسماء أو البادئات أو تتيح خدعة DLSYM. يجب أن تكون مكتبة الغلاف هذه مرتبطة ديناميكيًا (لتجنب تعارضات الرموز). يمكن للمكتبة الديناميكية بعد ذلك أن يكون لها مكتبة ثابتة قديمة مضمنة فيها. فقط تأكد من عدم تصدير الرموز من المكتبة الثابتة عند صنع مكتبة التفاف الديناميكية.

لا يمكنك حل هذا في وقت الرابط ، لذلك ستحتاج إلى حله في وقت التشغيل عبر المكتبات الديناميكية. يتم خبز رمز هذه الوظائف بشكل أساسي بمجرد إنشاء المكتبة. إذا قامت مكتبتان بتصدير نفس الرمز ، فلا يمكن ربطهما بشكل ثابت.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top