3. ÇØ°á ¹æ¹ý

3.1. extern "C"

C++¿¡´Â extern "C"¶ó´Â, C bindingÀ¸·Î ÇÔ¼ö¸¦ Á¤ÀÇÇϴ Ưº°ÇÑ Å°¿öµå°¡ ÀÖ½À´Ï´Ù. extern "C"·Î¼­ ¼±¾ðµÈ ÇÔ¼ö´Â Có·³ ÇÔ¼öÀÇ À̸§À» symbolÀÇ À̸§À¸·Î »ç¿ëÇÕ´Ï´Ù. ÀÌ·¯ÇÑ ÀÌÀ¯·Î, ¸â¹öÇÔ¼ö°¡ ¾Æ´Ñ ÇÔ¼öµé¸¸ÀÌ extern "C"·Î¼­ ¼±¾ðµÉ ¼ö ÀÖ°í, ÀÌ·¯ÇÑ ÇÔ¼öµéÀº ¿À¹ö·ÎµùÀ» ÇÒ ¼ö ¾ø½À´Ï´Ù.

ÀÌ·± ½ÉÇÑ Á¦ÇÑÀÌ ÀÖÁö¸¸, extern "C"ÇÔ¼ö´Â C ÇÔ¼öó·³ dlopenÀ» ½á¼­ µ¿ÀûÀ¸·Î ÀûÀçÇÒ ¼ö Àֱ⠶§¹®¿¡ ¸Å¿ì À¯¿ëÇÕ´Ï´Ù.

À̰ÍÀº extern "C"·Î ¼±¾ðµÈ ÇÔ¼ö°¡ C++ Äڵ带 Æ÷ÇÔÇÒ ¼ö ¾ø´Ù´Â °ÍÀ» ÀǹÌÇÏ´Â °ÍÀ̾ƴմϴÙ. ÀÌ·± ÇÔ¼ö´Â ¾î´À Á¾·ùÀÇ ÀÎÀÚ¶óµµ ¹ÞÀ» ¼ö ÀÖ°í, C++ÀÇ Æ¯Â¡À» ¾µ ¼ö ÀÖ½À´Ï´Ù.

3.2. ÇÔ¼ö¸¦ ÀûÀçÇÏ´Â ¹ý

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 "C" int foo;
extern "C" void bar();
            
extern "C" {
     extern int foo;
     extern void bar();
 }

extern°ú externÀÌ ¾Æ´Ñ ÇÔ¼öÀÇ ¼±¾ð¿¡´Â Â÷À̰¡ ¾ø±â¶§¹®¿¡, ´ç½ÅÀÌ ¾î¶°ÇÑ º¯¼öµµ ¼±¾ðÇÏÁö ¾Ê´Â ÇÑ ¹®Á¦°¡ ¾ø½À´Ï´Ù. ´ç½ÅÀÌ º¯¼ö¸¦ ¼±¾ðÇÑ´Ù¸é,´ÙÀ½ÀÇ µÎ ¼±¾ð ¹æ¹ýÀº °°Áö ¾Ê´Ù´Â °ÍÀ» ¸í½ÉÇØ¾ß ÇÕ´Ï´Ù.

extern "C" int foo;
extern "C" {
    int foo;
}

Á» ´õ ÀÚ¼¼ÇÑ ¼³¸íÀ» ¿øÇϽøé, paragraph 7¿¡ ÁÖÀǸ¦ ±â¿ï¿© [ISO14882]ÀÇ 7.5¸¦ Àо½Ã°Å³ª, [STR2000]ÀÇ paragraph 9.2.4.¸¦ ÂüÁ¶ÇØÁֽʽÿÀ.

¿ÜºÎ º¯¼ö·Î ¹«¾ð°¡¸¦ Çϱâ Àü¿¡, see alsoºÎºÐ¿¡ ÀûÇô ÀÖ´Â ¹®¼­µéÀ» Á¤µ¶ÇØÁֽñ⠹ٶø´Ï´Ù.

3.3. Ŭ·¡½º¸¦ ÀûÀçÇÏ´Â ¹ý

Ŭ·¡½º¸¦ ÀûÀçÇÏ´Â °ÍÀº Á» ´õ ¾î·Æ½À´Ï´Ù. ¿Ö³ÄÇÏ¸é ¿ì¸®´Â Ŭ·¡½ºÀÇÀνºÅϽº¸¦ ÇÊ¿ä·Î ÇÏÁö, ÇÔ¼ö¿¡ ´ëÇÑ Æ÷ÀÎÅ͸¦ ÇÊ¿ä·Î ÇÏ´Â°Ô ¾Æ´Ï±â ¶§¹®ÀÔ´Ï´Ù.

Ŭ·¡½º°¡ ½ÇÇàÆÄÀÏ¿¡ Á¤ÀǵǾî ÀÖÁö ¾ÊÀºµ¥´Ù°¡,(¸î¸î »óȲ¿¡¼­´Â) Ŭ·¡½ºÀÇ À̸§Á¶Â÷µµ ¾Ë ¼ö ¾ø±â ¶§¹®¿¡, ¿ì¸®´Â 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;
}

Ŭ·¡½º¸¦ ÀûÀçÇÒ¶§ ÁÖÀÇÇØ¾ß ÇÒ Á¡ÀÌ ¸î°¡Áö ÀÖ½À´Ï´Ù: