C++¿¡´Â extern "C"¶ó´Â, C bindingÀ¸·Î ÇÔ¼ö¸¦ Á¤ÀÇÇϴ Ưº°ÇÑ Å°¿öµå°¡ ÀÖ½À´Ï´Ù. extern "C"·Î¼ ¼±¾ðµÈ ÇÔ¼ö´Â Có·³ ÇÔ¼öÀÇ À̸§À» symbolÀÇ À̸§À¸·Î »ç¿ëÇÕ´Ï´Ù. ÀÌ·¯ÇÑ ÀÌÀ¯·Î, ¸â¹öÇÔ¼ö°¡ ¾Æ´Ñ ÇÔ¼öµé¸¸ÀÌ extern "C"·Î¼ ¼±¾ðµÉ ¼ö ÀÖ°í, ÀÌ·¯ÇÑ ÇÔ¼öµéÀº ¿À¹ö·ÎµùÀ» ÇÒ ¼ö ¾ø½À´Ï´Ù.
ÀÌ·± ½ÉÇÑ Á¦ÇÑÀÌ ÀÖÁö¸¸, extern "C"ÇÔ¼ö´Â C ÇÔ¼öó·³ dlopenÀ» ½á¼ µ¿ÀûÀ¸·Î ÀûÀçÇÒ ¼ö Àֱ⠶§¹®¿¡ ¸Å¿ì À¯¿ëÇÕ´Ï´Ù.
À̰ÍÀº extern "C"·Î ¼±¾ðµÈ ÇÔ¼ö°¡ C++ Äڵ带 Æ÷ÇÔÇÒ ¼ö ¾ø´Ù´Â °ÍÀ» ÀǹÌÇÏ´Â °ÍÀ̾ƴմϴÙ. ÀÌ·± ÇÔ¼ö´Â ¾î´À Á¾·ùÀÇ ÀÎÀÚ¶óµµ ¹ÞÀ» ¼ö ÀÖ°í, C++ÀÇ Æ¯Â¡À» ¾µ ¼ö ÀÖ½À´Ï´Ù.
C++¿¡¼ ÇÔ¼ö´Â dlsymÀ» ÅëÇØ Có·³ ÀûÀçµË´Ï´Ù. ´ç½ÅÀÌ ÀûÀçÇϰíÀÚ ÇÏ´Â ÇÔ¼ö´Â symbolÀÇ À̸§ÀÌ ¾û¸ÁÀ¸·Î µÇÁö ¾Êµµ·Ï(name manglingÀÌ ÀÌ·ç¾îÁöÁö ¾Êµµ·Ï), extern "C"·Î¼ÀÇ ÀÚ°ÝÀ» °®Ãç¾ß ÇÒ °ÍÀÔ´Ï´Ù.
¿¹ 1. ÇÔ¼ö¸¦ ÀûÀçÇϱâ
main.cpp:
#include <iostream> #include <dlfcn.h> int main() { using std::cout; using std::cerr; cout << "C++ dlopen demo\n\n"; // open the library cout << "Opening hello.so...\n"; void* handle = dlopen("./hello.so", RTLD_LAZY); if (!handle) { cerr << "Cannot open library: " << dlerror() << '\n'; return 1; } // load the symbol cout << "Loading symbol hello...\n"; typedef void (*hello_t)(); hello_t hello = (hello_t) dlsym(handle, "hello"); if (!hello) { cerr << "Cannot load symbol 'hello': " << dlerror() << '\n'; dlclose(handle); return 1; } // use it to do the calculation cout << "Calling hello...\n"; hello(); // close the library cout << "Closing library...\n"; dlclose(handle); } |
hello.cpp:
#include <iostream> extern "C" void hello() { std::cout << "hello" << '\n'; } |
hello¶ó´Â ÇÔ¼ö´Â hello.cpp¿¡¼ extern "C"·Î ¼±¾ðµÇ¾ú½À´Ï´Ù. À̰ÍÀº main.cpp¿¡¼ dlsymÀ» »ç¿ëÇÏ¿© ÀûÀçÇÒ ¼ö ÀÖ½À´Ï´Ù. ÇÔ¼ö´Â extern "C" ·Î¼ÀÇ ÀÚ°ÝÀ» °®Ãß¾î¾ß ÇÕ´Ï´Ù. ±×·¸Áö ¾Ê´Ù¸é ¿ì¸®´Â hello ÇÔ¼öÀÇ symbolÀÇ À̸§À» ¾Ë ¼ö ¾øÀ»Å״ϱî¿ä.
ÁÖÀÇ |
extern "C"ÀÇ ¼±¾ð¿¡´Â µÎ°¡ÁöÀÇ ´Ù¸¥ ÇüŰ¡ ÀÖ½À´Ï´Ù: Çϳª´Â À§¿¡¼ ½è´øextern "C"ÀÇ ¹æ¹ýÀ̰í, ¶Ç ´Ù¸¥ Çϳª´Â extern "C" { ¡¦ }ÇüÅ·ΠÁß°ýÈ£ »çÀÌ¿¡ ¼±¾ðÀÌ µé¾î°¡´Â ¹æ¹ýÀÔ´Ï´Ù. ù¹øÂ°(inline)ÇüÅ´ extern ¿¬°á°ú C ¾ð¾î ¿¬°áÀ» °®½À´Ï´Ù. µÎ¹øÂ° ÇüÅ´ C¾ð¾î ¿¬°á¿¡¸¸ ¿µÇâÀ» ³¢Ä¨´Ï´Ù. µû¶ó¼ ¾Æ·¡ÀÇ µÎ °¡Áö ¼±¾ð ¹æ¹ýÀº µ¿ÀÏÇÑ °ÍÀÔ´Ï´Ù. extern°ú externÀÌ ¾Æ´Ñ ÇÔ¼öÀÇ ¼±¾ð¿¡´Â Â÷À̰¡ ¾ø±â¶§¹®¿¡, ´ç½ÅÀÌ ¾î¶°ÇÑ º¯¼öµµ ¼±¾ðÇÏÁö ¾Ê´Â ÇÑ ¹®Á¦°¡ ¾ø½À´Ï´Ù. ´ç½ÅÀÌ º¯¼ö¸¦ ¼±¾ðÇÑ´Ù¸é,´ÙÀ½ÀÇ µÎ ¼±¾ð ¹æ¹ýÀº °°Áö ¾Ê´Ù´Â °ÍÀ» ¸í½ÉÇØ¾ß ÇÕ´Ï´Ù.Á» ´õ ÀÚ¼¼ÇÑ ¼³¸íÀ» ¿øÇϽøé, paragraph 7¿¡ ÁÖÀǸ¦ ±â¿ï¿© [ISO14882]ÀÇ 7.5¸¦ Àо½Ã°Å³ª, [STR2000]ÀÇ paragraph 9.2.4.¸¦ ÂüÁ¶ÇØÁֽʽÿÀ. ¿ÜºÎ º¯¼ö·Î ¹«¾ð°¡¸¦ Çϱâ Àü¿¡, see alsoºÎºÐ¿¡ ÀûÇô ÀÖ´Â ¹®¼µéÀ» Á¤µ¶ÇØÁֽñ⠹ٶø´Ï´Ù. |
Ŭ·¡½º¸¦ ÀûÀçÇÏ´Â °ÍÀº Á» ´õ ¾î·Æ½À´Ï´Ù. ¿Ö³ÄÇÏ¸é ¿ì¸®´Â Ŭ·¡½ºÀÇÀνºÅϽº¸¦ ÇÊ¿ä·Î ÇÏÁö, ÇÔ¼ö¿¡ ´ëÇÑ Æ÷ÀÎÅ͸¦ ÇÊ¿ä·Î ÇÏ´Â°Ô ¾Æ´Ï±â ¶§¹®ÀÔ´Ï´Ù.
Ŭ·¡½º°¡ ½ÇÇàÆÄÀÏ¿¡ Á¤ÀǵǾî ÀÖÁö ¾ÊÀºµ¥´Ù°¡,(¸î¸î »óȲ¿¡¼´Â) Ŭ·¡½ºÀÇ À̸§Á¶Â÷µµ ¾Ë ¼ö ¾ø±â ¶§¹®¿¡, ¿ì¸®´Â new ¸¦ ÀÌ¿ëÇÏ¿© Ŭ·¡½ºÀÇ ÀνºÅϽº¸¦ »ý¼ºÇÒ ¼ö ¾ø½À´Ï´Ù.
À̰ÍÀº ´ÙÇü¼º(polymorphism) À» ÅëÇØ ÇØ°áÇÒ ¼ö ÀÖ½À´Ï´Ù. ¿ì¸®´Â ±â¹Ý Ŭ·¡½º, °¡»óÀÇ ¸â¹ö¸¦ °¡Áö°í ÀÖ´Â ÀÎÅÍÆäÀ̽ºÅ¬·¡½º¸¦ ½ÇÇàÆÄÀϳ»¿¡ ¼±¾ðÇϰí, ½ÇÁ¦ ±¸ÇöºÎÀÇ Å¬·¡½º¸¦ ¸ðµâ ¿¡ ¼±¾ðÇÕ´Ï´Ù. ÀϹÝÀûÀ¸·Î ÀÎÅÍÆäÀ̽º Ŭ·¡½º´Â Ãß»óÀûÀÔ´Ï´Ù. (Ŭ·¡½º°¡ ¼ø¼ö°¡»óÇÔ¼ö(pure virtual function)À» °¡Áö°í ÀÖÀ»¶§ Ŭ·¡½º°¡ Ãß»óÀûÀ̶ó°í ÇÕ´Ï´Ù.)
Ŭ·¡½ºÀÇ µ¿ÀûÀÎ ÀûÀç´Â ÀϹÝÀûÀ¸·Î Ç÷¯±×ÀÎ — ¸íÈ®ÇÏ°Ô Á¤ÀÇµÈ ÀÎÅÍÆäÀ̽º¸¦ º¸¿©ÁÖ¾î¾ß ÇÏ´Â — ¿¡ ¾²À̱⠶§¹®¿¡, ¿ì¸®´Â ¾î·°Å³ª ÀÎÅÍÆäÀ̽º Ŭ·¡½º¿Í °Å±â¼ ÆÄ»ýµÈ ±¸ÇöºÎ Ŭ·¡½º¸¦ Á¤ÀÇÇØ¾ß ÇÕ´Ï´Ù.
´ÙÀ½À¸·Î,¸ðµâ ¾È¿¡Class factory functionÀ̶ó´Â µÎ°³ÀÇ µµ¿òÀ» ÁÖ´Â ÇÔ¼ö¸¦ Ãß°¡·Î ¼±¾ðÇØ¾ß ÇÕ´Ï´Ù. ÀÌ ÇÔ¼ö Áß Çϳª´Â Ŭ·¡½ºÀÇ ÀνºÅϽº¸¦ ¸¸µé°í ±×°ÍÀÇ Æ÷ÀÎÅ͸¦ ¹ÝȯÇÏ´Â ¿ªÇÒÀ» Çϰí, ¶Ç ´Ù¸¥ ÇϳªÀÇ ÇÔ¼ö´Â factory¿¡¼ ¸¸µé¾îÁø ÇÔ¼öÀÇ Æ÷ÀÎÅ͸¦ ¹Þ¾Æ ±×°Í(Ŭ·¡½ºÀÇ ÀνºÅϽº)¸¦ ÆÄ±«ÇÏ´Â ¿ªÇÒÀ» ÇÕ´Ï´Ù. ÀÌ µÎ ÇÔ¼ö´Â extern "C"ÀÇ ÀÚ°ÝÀ» °¡Áö°í ÀÖ¾î¾ß ÇÕ´Ï´Ù.
Ŭ·¡½º¸¦ ¸ðµâ¿¡¼ ¾²±â À§Çؼ,µÎ°³ÀÇ factory functionÀ» ¿ì¸®°¡ helloÇÔ¼ö¸¦ ÀûÀçÇß´ø °Íó·³dlsymÀ» »ç¿ëÇÏ¿© ÀûÀçÇϽʽÿÀ.±×·³ ¿ì¸®´Â ¿ì¸®°¡ ¿øÇÏ´Â ¸¸ÅÀÇ ÀνºÅϽº¸¦ »ý¼ºÇÒ¼öµµ ÀÖ°í, ÆÄ±«ÇÒ ¼öµµ ÀÖ½À´Ï´Ù.
¿¹ 2. Ŭ·¡½º¸¦ ÀûÀçÇÏ´Â ¹ý
¿©±â¼ ¿ì¸®´Â ÀϹÝÀûÀδٰ¢ÇüÀ» ÀÎÅÍÆäÀ̽º·Î Çϰí, »ï°¢ÇüÀ» ±¸ÇöºÎºÐÀ¸·Î ÇÒ °ÍÀÔ´Ï´Ù.
main.cpp:
#include "polygon.hpp" #include <iostream> #include <dlfcn.h> int main() { using std::cout; using std::cerr; // load the triangle library void* triangle = dlopen("./triangle.so", RTLD_LAZY); if (!triangle) { cerr << "Cannot load library: " << dlerror() << '\n'; return 1; } // load the symbols create_t* create_triangle = (create_t*) dlsym(triangle, "create"); destroy_t* destroy_triangle = (destroy_t*) dlsym(triangle, "destroy"); if (!create_triangle || !destroy_triangle) { cerr << "Cannot load symbols: " << dlerror() << '\n'; return 1; } // create an instance of the class polygon* poly = create_triangle(); // use the class poly->set_side_length(7); cout << "The area is: " << poly->area() << '\n'; // destroy the class destroy_triangle(poly); // unload the triangle library dlclose(triangle); } |
polygon.hpp:
#ifndef POLYGON_HPP #define POLYGON_HPP class polygon { protected: double side_length_; public: polygon() : side_length_(0) {} void set_side_length(double side_length) { side_length_ = side_length; } virtual double area() const = 0; }; // the types of the class factories typedef polygon* create_t(); typedef void destroy_t(polygon*); #endif |
triangle.cpp:
#include "polygon.hpp" #include <cmath> class triangle : public polygon { public: virtual double area() const { return side_length_ * side_length_ * sqrt(3) / 2; } }; // the class factories extern "C" polygon* create() { return new triangle; } extern "C" void destroy(polygon* p) { delete p; } |
Ŭ·¡½º¸¦ ÀûÀçÇÒ¶§ ÁÖÀÇÇØ¾ß ÇÒ Á¡ÀÌ ¸î°¡Áö ÀÖ½À´Ï´Ù:
´ç½ÅÀº ÀνºÅϽº¸¦ »ý¼ºÇÏ´Â ÇÔ¼ö¿Í ÆÄ±«ÇÏ´Â ÇÔ¼ö¸¦ ¸ðµÎ Á¦°øÇØ¾ß ÇÕ´Ï´Ù. ¶Ç ´ç½ÅÀÌ ÀνºÅϽº¸¦ ÆÄ±«ÇÒ¶§¿¡´Â ½ÇÇàÆÄÀÏ ³»¿¡¼ delete¸¦ ÀÌ¿ëÇØ¼ Áö¿ìÁö ¸¶½Ã°í ,Ç×»ó ¸ðµâ·Î ³Ñ°Ü¼ Áֽñ⠹ٶø´Ï´Ù. ÀÌ´Â C++ ¿¡¼ new¿Í delete °¡ ¿À¹ö·Îµù µÉ ¼ö Àֱ⠶§¹®ÀÔ´Ï´Ù. ÀÌ °æ¿ì¿¡ ¼·Î ¸ÂÁö ¾Ê´Â new¿Í delete °¡ È£ÃâµÉ ¼ö ÀÖ°í, ±×·¸°Ô µÇ¸é ¸Þ¸ð¸® ´©¼ö³ª segmentation fault°¡ ÀϾ ¼öµµ ÀÖ½À´Ï´Ù.À̰ÍÀº ¸ðµâ°ú ½ÇÇàÆÄÀÏÀ» ¸µÅ©ÇÒ¶§ ¼·Î ´Ù¸¥ Ç¥ÁØ ¶óÀ̺귯¸®¸¦ »ç¿ëÇßÀ» °æ¿ì¿¡µµ Àû¿ëµË´Ï´Ù.
ÀÎÅÍÆäÀ̽º Ŭ·¡½ºÀÇ ¼Ò¸êÀÚ´Â ±¸ÇöºÎ Ŭ·¡½º¿¡ ¼Ò¸êÀÚ°¡ ¾ø´Â°æ¿ì¸¦ Á¦¿ÜÇϰí´Â °¡»ó(virtual)À̾î¾ß ÇÕ´Ï´Ù. ±×·¸Áö ¾ÊÀ¸¸é ±×°ÍÀº È£ÃâµÇÁö ¾ÊÀ» °ÍÀ̰í, ¸Þ¸ð¸® ´©¼ö³ª segmentation fault°¡ ÀϾ ¼öµµ ÀÖ½À´Ï´Ù.