দুটি লাইব্রেরি যদি একই নামের সাথে কোনও দ্বন্দ্ব তৈরি করে এমন কোনও ফাংশন সরবরাহ করে তবে আমার কী করা উচিত?


95

যদি আমার কাছে দুটি লাইব্রেরি থাকে যা সমান নাম সহ ফাংশন সরবরাহ করে তবে আমার কী করা উচিত?


4
এই স্থির গ্রন্থাগারগুলি নাকি গতিশীলভাবে সংযুক্ত?
Alnitak

আমাদের আরও বিশদ প্রয়োজন ... এই নামগুলি কি রফতানি করা হচ্ছে? নাকি সেগুলি কেবল অভ্যন্তরীণভাবে ব্যবহৃত হয়? নাম বদলাতে পারবেন?
জোহানেস স্কাউব - লিটব

তারা গতিশীলভাবে সংযুক্ত, উভয়ই। আমি নামগুলি পরিবর্তন করতে পারি না, যেহেতু আমার কাছে লাইব্রেরিগুলির মালিকানা নেই।
কিউইক

দুর্দান্ত প্রশ্ন। অবশ্যই এটা এই দুটি লাইব্রেরি যদি সব চিহ্ন একটি অনন্য আইডি দিয়ে পূর্বে সমাধান করা হয়েছে একটি সমস্যা হবে না (যেমন vorbis_..., sf_..., sdl_...)। এটি মূলত যা সি ++ নাম-গতি ফাংশনগুলির জন্য প্রতীক নামগুলিতে করে।
ভোর্তিকো

এটি একটি খুব আকর্ষণীয় প্রশ্ন তবে দুঃখজনকভাবে খুব অসমর্থিত যা অনেক বেশি বিস্তৃত উত্তর থাকার কারণ।
yugr

উত্তর:


53
  • আপনি যদি একটি বা উভয়ই নিয়ন্ত্রণ করেন: নাম পরিবর্তন করতে এবং পুনরায় সংকলন করতে একটি সম্পাদনা করুন বা সমানভাবে বেন এবং অজানা এর উত্তরগুলি দেখুন যা উত্স কোড অ্যাক্সেস ছাড়াই কাজ করবে ।
  • আপনি যদি এগুলির একটিতেও নিয়ন্ত্রণ না করেন তবে আপনি তাদের একটি মুছতে পারেন। এটি অন্য একটি ( স্ট্যাটিকালি লিঙ্কড !) লাইব্রেরি সংকলন করে যা আপত্তিজনক একটি ছাড়া মূলটির সমস্ত চিহ্নগুলি পুনরায় রফতানি করা ছাড়া আর কিছুই করে না, যা বিকল্প নামের একটি মোড়কের মাধ্যমে পৌঁছে যায়। কি ঝামেলা।
  • পরে যোগ করা হয়েছে: যেহেতু qeek বলেন গতিশীল লাইব্রেরি কথা বলা হচ্ছে, সমাধান দ্বারা প্রস্তাবিত Ferruccio এবং mouviciel সম্ভবত শ্রেষ্ঠ। (আমার মনে হয় অনেক আগের দিনগুলিতেই স্থির যোগসূত্রটি পূর্বনির্ধারিত ছিল It এটি আমার চিন্তার রঙিন।

এপ্রোপস মন্তব্যগুলি: "রফতানি" বলতে আমার অর্থ লাইব্রেরির সাথে সংযোগকারী মডিউলগুলিকে দৃশ্যমান করা --- externফাইল স্কোপে কীওয়ার্ডের সমতুল্য । এটি কীভাবে নিয়ন্ত্রণ করা হয় তা ওএস এবং লিঙ্কার নির্ভর। এবং এটি এমন কিছু যা আমাকে সর্বদা সন্ধান করতে হবে।


এটিও আমার প্রথম চিন্তা ছিল, তবে আপনি কি একই সংঘর্ষের সমস্যাটি শেষ করবেন না? শেষের দিকে, সম্পূর্ণ প্রকল্পটি সংযোগ করতে হবে - সংকলন / লিংক সময় বা রান সময় - যে সময়ে উভয় আপত্তিকর গ্রন্থাগারকে যেমন হয় তেমন লোড করতে হয়।
স্নিগ্গারফার্ডিমঙ্গাস

@ অজানা: মোড়ক অবশ্যই স্থির লিঙ্কেজ সহ সংকলিত হবে এবং আপত্তিজনক প্রতীকটি রফতানি করা উচিত নয়। তারপরে আপনি গতিশীলভাবে মোড়কে লিঙ্ক করতে পারেন। আরও স্পষ্টতার জন্য সম্পাদিত, ধন্যবাদ।
ডিএমকেই --- প্রাক্তন-মডারেটর বিড়ালছানা

যদি কিউকের সমস্যাটি ডিডিএল এবং স্ট্যাটিক লাইব্রেরি না নিয়ে থাকে তবে কীভাবে একটি মোড়ক দিয়ে একটি নতুন লাইব্রেরি তৈরি করা সম্ভব? যেহেতু, মোড়কটির গ্রন্থাগারটি আপনার প্রথম লাইব্রেরির সাথে সংযোগ স্থাপন করতে চান না এমন লাইব্রেরির কোনও ক্রিয়াকলাপটিকে গতিশীলভাবে আবদ্ধ করতে হবে।
jeffD

@ ডিএমকেই - "রফতানি" বলতে কী বোঝ?

4
সম্ভবত কেউ এই কৌশল একটি সাধারণ উদাহরণ দিতে পারে? একটি উদাহরণ, দুটি গ্রন্থাগার প্রতিটি একই নামের সাথে একটি ফাংশন ধারণ করে।

54

কোনও অবজেক্ট ফাইলে objcopy --redefine-sym old=new fileপ্রতীকটির নাম পরিবর্তন করা সম্ভব (ম্যান অ্যাজকপিটি দেখুন)।

তারপরে কেবল তাদের নতুন নামগুলি ব্যবহার করে ফাংশনগুলিতে কল করুন এবং নতুন অবজেক্ট ফাইলের সাথে লিঙ্ক করুন।


4
ভাল লাগল এটি একটি মেকফাইলে যুক্ত করতে তুচ্ছ হবে। লাইব্রেরিগুলি যদি কখনও আপডেট হয় তবে অন্য কয়েকটি সমাধানের তুলনায় একটি অবজকপি প্রবর্তন আপডেট করা অনেক সহজ।
সিগজুইস

9
শিরোনাম ফাইলগুলিতে প্রতীকগুলির নাম পরিবর্তন করতে ভুলবেন না।
mouviciel

^ সেড / অ্যাজক / পার্ল শিরোনামে চিহ্নগুলির নাম পরিবর্তন করতেও স্বয়ংক্রিয়ভাবে কার্যকর হবে
অ্যালেক্স রিঙ্কিং

16

উইন্ডোজ এর অধীনে, আপনি সেই লাইব্রেরিগুলির একটি মেমরিতে লোড করতে লোডলাইবারি () ব্যবহার করতে পারেন এবং তারপরে ফাংশন পয়েন্টারের মাধ্যমে ফাংশনগুলিতে কল এবং কল করতে হবে এমন প্রতিটি ফাংশনের ঠিকানা পেতে গেটপ্রোকএড্রেস () ব্যবহার করতে পারেন use

যেমন

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);

foo.dll এ বার নামে একটি ফাংশনের ঠিকানা পেয়ে তা কল করবে।

আমি জানি ইউনিক্স সিস্টেমগুলি অনুরূপ কার্যকারিতা সমর্থন করে তবে আমি তাদের নামগুলি ভাবতে পারি না।


dlopen dlsym, এবং dlclose। তবে ইউনিক্সের এনক্যাপসুলেশন উইন্ডোজের মতো কার্যকর নাও হতে পারে।
ব্যবহারকারীর 877329


8

এখানে একটি চিন্তা। একটি হেক্স সম্পাদক সম্পাদকে আপত্তিজনক লাইব্রেরিগুলির একটি খুলুন এবং আপত্তিজনক স্ট্রিংয়ের সমস্ত উপস্থিতি অন্য কোনও কিছুতে পরিবর্তন করুন। তারপরে আপনার ভবিষ্যতের সমস্ত কলগুলিতে নতুন নামগুলি ব্যবহার করতে সক্ষম হওয়া উচিত।

আপডেট: আমি এই প্রান্তে এটি করেছি এবং এটি কার্যকর বলে মনে হচ্ছে। অবশ্যই, আমি এটি পুরোপুরি পরীক্ষা করে দেখিনি - হেক্সডিট শটগান দিয়ে আপনার পা কেটে ফেলার এটি সত্যিই ভাল উপায় ছাড়া আর কিছু নাও হতে পারে।


আসলে একটি ভয়ঙ্কর সমাধান নয়। কিছুটা হ্যাকিশ, তবে আপনি যা করছেন তা প্রতীক টেবিলের স্ট্রিংগুলি পরিবর্তন করা। এতে আসল কার্যকরী ক্ষতি নেই।
ইভান তেরান

আপনি সম্ভবত গ্রন্থাগারের নতুন নামকরণ করতে চাইবেন - পাছে অন্য কেউ আসেন না, জিনিসটি আবার লোড করার চেষ্টা করছেন। আপনি একটি সংঘাত থেকে কয়েক ডজন বা কয়েকশতে যেতে চাই। =] স্ট্যাকওভারফ্লো সম্পর্কে আমি এটি পছন্দ করি: আমাদের কাছে একটি প্রশ্নের পরীক্ষিত উত্তর রয়েছে এবং এটিতে 3 টি ভোট রয়েছে। প্রথম (অসম্পূর্ণ) উত্তর: ১.. =]
স্নিগগারফার্ডিমুঙ্গাস ২

4
পুনরায় নামকরণের সুযোগগুলি সীমিত কারণ আপনি কেবলমাত্র নামগুলি সংক্ষিপ্ত করতে সক্ষম হবেন । লিনাক্সেও আপনার ইএলএফ হ্যাশ টেবিলগুলি আপডেট করাতে বেশ সময় লাগবে।
yugr

8

আপনার কাছে যদি .o ফাইল থাকে তবে এখানে একটি ভাল উত্তর: https://stackoverflow.com/a/6940389/4705766

সারসংক্ষেপ:

  1. objcopy --prefix-symbols=pre_string test.o .o ফাইলটিতে প্রতীকগুলির নাম পরিবর্তন করতে

বা

  1. objcopy --redefine-sym old_str=new_str test.o .o ফাইলটিতে নির্দিষ্ট চিহ্নটির নতুন নামকরণ করতে।

7

ধরে নিচ্ছি যে আপনি লিনাক্স ব্যবহার করেন আপনার প্রথমে যুক্ত করা দরকার

#include <dlfcn.h>

যথাযথ প্রসঙ্গে ফাংশন পয়েন্টার ভেরিয়েবল ঘোষণা করুন, উদাহরণস্বরূপ,

int (*alternative_server_init)(int, char **, char **);

Https://stackoverflow.com/a/678453/1635364 তে উল্লিখিত ফের্রুসিওর মতো , কার্যকর করে আপনি যে লাইব্রেরিটি ব্যবহার করতে চান তা লোড করুন (আপনার পছন্দসই পতাকাগুলি বেছে নিন)

void* dlhandle;
void* sym;

dlhandle = dlopen("/home/jdoe/src/libwhatnot.so.10", RTLD_NOW|RTLD_LOCAL);

আপনি যে ফাংশনটি পরে কল করতে চান তার ঠিকানাটি পড়ুন

sym = dlsym(dlhandle, "conflicting_server_init");

নিম্নলিখিত হিসাবে নির্ধারিত এবং নিক্ষিপ্ত

alternative_server_init = (int (*)(int, char**, char**))sym;

আসলটির চেয়ে একইভাবে কল করুন। শেষ পর্যন্ত, চালিয়ে আনলোড করুন

dlclose(dlhandle);


6

এগুলি একসাথে ব্যবহার করা উচিত নয়। যদি আমি সঠিকভাবে মনে রাখি তবে লিঙ্কার এ জাতীয় ক্ষেত্রে একটি ত্রুটি জারি করে।

আমি চেষ্টা না, কিন্তু একটি সমাধান সঙ্গে হতে পারে dlopen(), dlsym()এবং dlclose()আপনি প্রোগ্রামের মাধ্যমে গতিশীল লাইব্রেরি হ্যান্ডেল করার অনুমতি দেয়। আপনার যদি একই সাথে দুটি ফাংশনের প্রয়োজন না হয় তবে আপনি প্রথম লাইব্রেরিটি খুলতে পারবেন, প্রথম ফাংশনটি ব্যবহার করতে পারবেন এবং দ্বিতীয় গ্রন্থাগার / ফাংশনটি ব্যবহার করার আগে প্রথম লাইব্রেরিটি বন্ধ করতে পারবেন।


ধন্যবাদ এ নিয়ে ভাবিনি। যদিও, আমি একই সাথে উভয় থাকতে চাই।
কিউইক

যদি আমি একই সাথে উভয় ব্যবহার করতে চাই?
কিউজেডুয়া

@ কিউজুয়া: অন্যান্য আনসার (যেমন প্রতীক নামকরণের সাথে জড়িত) আপনার সমস্যার সমাধান করা উচিত।
mouviciel

4

এই সমস্যাটি হ'ল সি ++ এর নেমস্পেস রয়েছে। 2 টি তৃতীয় পক্ষের একই নাম সমেত লিবগুলির জন্য গিতে আসলেই দুর্দান্ত সমাধান নেই।

যদি এটি একটি গতিশীল অবজেক্ট হয় তবে আপনি সম্ভবত ভাগ করে নেওয়া অবজেক্টগুলি (লোডলিবারি / ড্লোপেন / ইত্যাদি) স্পষ্টভাবে লোড করতে সক্ষম হবেন এবং এটিকে ফ্যাশনে কল করতে পারবেন। পর্যায়ক্রমে, যদি একই কোডে আপনার একই সাথে উভয় লিবসের প্রয়োজন না হয় তবে আপনি স্থির লিঙ্কিংয়ের সাহায্যে কিছু করতে পারেন (যদি আপনার কাছে .lib / .a ফাইল থাকে)।

এই সমাধানগুলির কোনওটি অবশ্যই সমস্ত প্রকল্পের জন্য প্রযোজ্য নয়।


4
হ্যাঁ. এই সাধারণ প্রশ্নের জন্য এটি ভাল উত্তর বলে মনে হচ্ছে। তবে - আপনি একই সংকলকটিতে সবকিছু এক সাথে সংকলন করলে নেমস্পেসগুলি দুর্দান্ত are হুররে, কোনও নামেই সংঘাত নেই। তবে আপনি যদি বাইনারি আকারে একটি লাইব্রেরি পেয়ে থাকেন এবং এটি অন্য সংকলকের সাথে সংহত করতে চান তবে - শুভকামনা। অবজেক্ট ফাইলে নামের ম্যাংলিংয়ের নিয়মগুলি হ'ল প্রথম বাঁধা (বহিরাগত "সি" সহায়তা করতে পারে, যা নামস্থানগুলির প্রভাবকে অগ্রাহ্য করে)।
টমাসজ গেন্ডার

3

দিব্যি? যতদূর আমি সচেতন, আপনার কাছে দুটি লাইব্রেরি রয়েছে যা একই নামের সাথে লিঙ্ক পয়েন্টগুলি প্রকাশ করে এবং আপনার উভয়ের বিপরীতে লিঙ্ক করা দরকার হলে আপনি তেমন কিছু করতে পারবেন না।


12
কসম অবশ্যই প্রথম পদক্ষেপ। এ ব্যপারে কোন সন্দেহ নেই.
dmckee --- প্রাক্তন-মডারেটর বিড়ালছানা

4
"আপনি করতে পারেন এমন অনেক কিছুই নেই" - এটি কি এখনও প্রাসঙ্গিক? অন্যান্য উত্তর অসংখ্য বিভিন্ন সমাধান।
yugr

2

আপনার মধ্যে একটির চারপাশে একটি মোড়ক লাইব্রেরি লেখা উচিত। আপনার মোড়কের লাইব্রেরিতে স্বতন্ত্র নামের প্রতীকগুলি প্রকাশ করা উচিত এবং অ-অনন্য নামের প্রতীকগুলি প্রকাশ করা উচিত নয়।

আপনার অন্য বিকল্পটি শিরোনাম ফাইলে ফাংশনটির নাম এবং লাইব্রেরি অবজেক্ট আর্কাইভের প্রতীকটির নতুন নামকরণ করা।

যে কোনও উপায়ে, উভয়ই ব্যবহার করা, এটি হ্যাকের কাজ হবে।



1

প্রশ্নটি এক দশক পুরানো কাছাকাছি পৌঁছেছে, তবে সর্বদা নতুন অনুসন্ধান রয়েছে ...

ইতিমধ্যে উত্তর হিসাবে, --redefine - সিম পতাকা সঙ্গে অবজকপি লিনাক্স মধ্যে ভাল পছন্দ। উদাহরণস্বরূপ, https://linux.die.net/man/1/objcopy দেখুন সম্পূর্ণ ডকুমেন্টেশনের জন্য । এটি কিছুটা জটিল কারণ আপনি পরিবর্তনগুলি করার সময় মূলত পুরো লাইব্রেরিটি অনুলিপি করছেন এবং প্রতিটি আপডেটের জন্য এই কাজটির পুনরাবৃত্তি করা প্রয়োজন। তবে কমপক্ষে এটি কাজ করা উচিত।

উইন্ডোজের জন্য, গতিময়ভাবে লাইব্রেরিটি লোড করা একটি সমাধান এবং লিনাক্সের ড্লোপেন বিকল্পের মতো স্থায়ীভাবে হবে। তবে ড্লোপেন () এবং লোডলিবারি () উভয়ই অতিরিক্ত কোড যুক্ত করে যা এড়ানো যেতে পারে যদি কেবলমাত্র ইস্যুটির নাম নকল হয়। এখানে উইন্ডোজ সলিউশনটি অ্যাজজকপি পদ্ধতির চেয়ে আরও মার্জিত: কেবল লিঙ্কারে বলুন যে কোনও লাইব্রেরির চিহ্নগুলি অন্য কোনও নামে পরিচিত এবং সেই নামটি ব্যবহার করুন। এটি করার কয়েকটি পদক্ষেপ রয়েছে। আপনাকে একটি ডিএফ ফাইল তৈরি করতে হবে এবং রফতানির বিভাগে নাম অনুবাদ সরবরাহ করতে হবে। Https://msdn.microsoft.com/en-us/library/hyx1zcd3.aspx দেখুন (VS2015, এটা শেষ পর্যন্ত নতুন সংস্করণে দ্বারা প্রতিস্থাপিত হবে) অথবা http://www.digitalmars.com/ctg/ctgDefFiles.html(সম্ভবত আরও স্থায়ী) একটি ডিএফ ফাইলের সম্পূর্ণ সিনট্যাক্স বিশদের জন্য। প্রক্রিয়াটি হ'ল লাইব্রেরির একটির জন্য একটি ডিএফ ফাইল তৈরি করে একটি ডিআইবি ফাইল তৈরির জন্য এই ডিএফ ফাইলটি ব্যবহার করুন এবং তারপরে সেই লিব ফাইলের সাথে লিঙ্ক করুন। (উইন্ডোজ ডিএলএলগুলির জন্য, লিব ফাইলগুলি কেবল লিঙ্কিংয়ের জন্য ব্যবহৃত হয়, কোড এক্সিকিউশন নয়)) লাইব ফাইলটি তৈরির প্রক্রিয়াটির জন্য একটি .dll ফাইল এবং একটি শিরোনাম ফাইল থাকাকালীন একটি .lib ফাইল কীভাবে তৈরি করবেন তা দেখুন । এখানে কেবলমাত্র পার্থক্যটিই ডাকনাম যুক্ত করা হচ্ছে।

লিনাক্স এবং উইন্ডোজ উভয়ের জন্যই, লাইব্রেরির শিরোনামগুলির ফাংশনগুলির নাম পরিবর্তন করুন যাদের নাম প্রবণতাযুক্ত রয়েছে। অন্য একটি বিকল্প যা কাজ করা উচিত তা হ'ল নতুন নামগুলি উল্লেখ করে ফাইলগুলিতে # ডিফাইন পুরাতন_নামের নতুন নাম, # লাইব্রেরির শিরোনামগুলি অন্তর্ভুক্ত করা হচ্ছে যার রফতানি আলাদা করে দেওয়া হচ্ছে, এবং তারপরে কলারের মধ্যে # অপরিষ্কার পুরাতন_নামের নাম অন্তর্ভুক্ত করুন। লাইব্রেরি ব্যবহার করে যদি অনেকগুলি ফাইল থাকে, তবে একটি সহজ বিকল্প হ'ল শিরোনাম বা শিরোনামগুলি তৈরি করে যা সংজ্ঞায়িত করে, অন্তর্ভুক্ত করে এবং আনডফগুলিকে আবৃত করে এবং তারপরে সেই শিরোনামটি ব্যবহার করে।

আশা করি এই তথ্যটি সহায়ক ছিল!


0

আমি কখনই dlsym, dlopen, dlerror, dlclose, dlvsym, ইত্যাদি ব্যবহার করি নি, তবে আমি ম্যান পৃষ্ঠাটি দেখছি, এবং এটি libm.so খোলার এবং কোস ফাংশনটি বের করার উদাহরণ দেয়। ড্লোপেন কি সংঘর্ষের সন্ধানের প্রক্রিয়াটি অতিক্রম করে? যদি এটি না হয় তবে ওপি কেবলমাত্র দুটি লাইব্রেরি ম্যানুয়ালি লোড করতে পারে এবং তার লাইব্রেরিগুলি সরবরাহ করে এমন সমস্ত কার্যক্রমে নতুন নাম নির্ধারণ করতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.