जब आप आवेदन से जुड़ा हुआ है, अनसुलझे प्रतीक पुस्तकालयों उपलब्ध कराने का उपयोग कर का समाधान हो जाएगा। आप एक समारोह को परिभाषित नहीं है, तो यह लिंकिंग, इसलिए, जुड़ा हुआ है, कि प्रतीक librmath का उपयोग कर हल करने इस मामले में की कोशिश करेंगे के दौरान एक अनसुलझे प्रतीक होगा। यदि एक या अधिक प्रतीकों का समाधान नहीं किया जा सकता है, तो आपको एक लिंकर त्रुटि मिल जाएगी।
हालांकि, यदि आप अपने कोड में फ़ंक्शन को परिभाषित करते हैं, तो इसे पहले से ही लिंक करने के दौरान परिभाषित किया जाएगा, इसलिए बाहरी पुस्तकालयों के प्रतीकों का उपयोग करके इसे हल करने की आवश्यकता नहीं होगी।
आप ऐसा नहीं कर सकते क्या अपने आवेदन में एक बार से एक ही प्रतीक अधिक परिभाषित करने के लिए है।
संपादित करें: चूंकि किसी अन्य उत्तर में बहुत बहस है, इसलिए मैंने एक व्यावहारिक उदाहरण बना दिया है। मैं एक साझा वस्तु (विंडोज़ में DLL- के समान) है, जो परिभाषित करता है और एक समारोह foo
निर्यात बना लिया है:
//lib.h
extern "C" {
void foo();
void bar();
};
//lib.cpp
#include <iostream>
#include "lib.h"
void foo() {
std::cout << "From lib\n";
}
void bar() {
std::cout << "Bar, calling foo\n";
foo();
}
आदेश में इस साझा वस्तु का परीक्षण करने के लिए, मैं एक आवेदन जो इसके साथ जुड़ा हुआ है बना लिया है :
//test.cpp
#include <iostream>
#include "lib.h"
void foo() {
std::cout << "From app\n";
}
int main() {
bar();
}
मैं दोनों में संकलित किया है, साझा वस्तु और आवेदन:
g++ lib.cpp -o libtest.so -Wall -fPIC -shared -Wl,--export-dynamic -Wl,-soname,libtest.so -Wl,-z,defs
g++ test.cpp -o test -L. -ltest
और जब मैं test
निष्पादित, 01,239,140 करने के लिए पुस्तकालय की स्थापना पथ
[email protected]:/tmp$ LD_LIBRARY_PATH="." ./test
Bar, calling foo
From app
आप देख सकते हैं, foo
समारोह आवेदन (नहीं साझा वस्तु) में परिभाषित कहा जाता है:, इसलिए मेरे साझा वस्तु लोड किया जा सकता, मैं इस उत्पादन मिलता है। आप मूल रूप से किसी साझा ऑब्जेक्ट में प्रत्येक निर्यात किए गए प्रतीक के लिए ऐसा कर सकते हैं।
EDIT2: मैंने lib.h में एक और निर्यात किया गया फ़ंक्शन जोड़ा है। एप्लिकेशन अब इस फ़ंक्शन को कॉल करता है, जो कॉलिंग को समाप्त करता है। परिणाम अपेक्षित के समान है।
EDIT3: ठीक है, चलो गहरे जाओ।
Dump of assembler code for function [email protected]:
0x0804855c <+0>: jmp DWORD PTR ds:0x804a004
0x08048562 <+6>: push 0x8
0x08048567 <+11>: jmp 0x804853c
हम 0x804a004
संबोधित करने के लिए जाते हैं:
Dump of assembler code for function _GLOBAL_OFFSET_TABLE_:
0x08049ff4 <+0>: or BYTE PTR [edi+0x804],bl
0x08049ffa <+6>: add BYTE PTR [eax],al
0x08049ffc <+8>: add BYTE PTR [eax],al
0x08049ffe <+10>: add BYTE PTR [eax],al
.....
आप देख सकते हैं, यह वैश्विक ऑफसेट टेबल पर कूद रहा है इस समारोह bar
से डंप है। आप GOT here और here के बारे में पढ़ सकते हैं। डायनामिक प्रतीकों (जिन्हें रनटाइम पर हल किया जाता है) इस तालिका में संग्रहीत होते हैं। जब भी आप एक प्रतीक को कॉल करते हैं जिसे रनटाइम पर हल किया जाना चाहिए, तो आप वास्तव में इस तालिका में कूदते हैं, और उसके बाद इस तालिका की संबंधित प्रविष्टि में संग्रहीत पते पर जाएं। चूंकि एप्लिकेशन foo
को परिभाषित करता है, इसलिए GOT में test.cpp
से परिभाषा का पता होता है, न कि हमारे साझा ऑब्जेक्ट में से एक।
EDIT4: ठीक है, अंतिम संपादन। दस्तावेज़ से हवाला देते हुए:
आप वर्दी यादृच्छिक संख्या जनरेटर
double unif_rand(void)
की आपूर्ति या (आपूर्ति की एक का उपयोग करें और एक गतिशील पुस्तकालय या DLL के साथ आपूर्ति की एक का उपयोग करना होगा करने की आवश्यकता होगी (...)
प्रलेखन स्पष्ट रूप से कहते हैं कि आप आप unif_rand
के कार्यान्वयन के मालिक हैं आप गतिशील पुस्तकालय उपयोग कर रहे हैं प्रदान नहीं कर सकते हैं। इसलिए, मुझे विश्वास है कि मैं क्या ने कहा, वास्तव में ans आपका प्रश्न पूछता है
मेरा अनुमान होगा कि समारोह डीईएफ़ ताकि यदि आप इसे परिभाषित करते हैं, तो तुम्हारा लिंकर से पहले पाया जाता है, तो एक पहले से ही वहाँ नजरअंदाज कर दिया जाएगा एक #ifdef में है। – baash05