본문 바로가기

Mac&iOS

c++ 동적 로딩 관련 개발 가이드

출처 : https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/DynamicLibraryUsageGuidelines.html


c++로 된 dylib를 런타임에 동적 로딩후 사용하기 위해서는 new로 생성할 수는 없고, 대신 dylib에서 new를 대신 해주는 Factory function을 제공해줘야 한다.


마찬가지로 소멸자를 호출 할 수 없으므로 마찬가지로 function을 제공해야 한다.


/* File: Person.h */

class Person {

    private:

        char _person_name[30];

    public:

        Person();

        Person(char* name);

        virtual void set_name(char person_name[]);

        virtual char* name();

};

 

// Constructor functions and function types.

extern "C" Person* NewPerson(void);

typedef Person * Person_creator(void);

extern "C" Person* NewPersonWithName(char name[]);

typedef Person * PersonWithName_creator(char name[]);

 

// Destructor function and function type.

extern "C" void DeletePerson(Person* person);

typedef void Person_disposer(Person*);



/* File: Person.cpp */

#include <iostream>

#include "Person.h"

 

#define EXPORT __attribute__((visibility("default")))

 

EXPORT

Person::Person() {

    char default_name[] = "<no value>";

    this->set_name(default_name);

}

 

EXPORT

Person::Person(char *name) {

    this->set_name(name);

}

 

EXPORT

Person* NewPerson(void) {

    return new Person;

}

 

EXPORT

Person* NewPersonWithName(char name[]) {

    return new Person(name);

}

 

EXPORT

void DeletePerson(Person* person) {

    delete person;

}

 

void Person::set_name(char name[]) {

    strcpy(_person_name, name);

}

 

char* Person::name(void) {

    return _person_name;

}



/* File: Client.cpp */

#include <iostream>

#include <dlfcn.h>

#include "Person.h"

 

int main() {

    using std::cout;

    using std::cerr;

 

    // Open the library.

    void* lib_handle = dlopen("./libPerson.dylib", RTLD_LOCAL);

    if (!lib_handle) {

        exit(EXIT_FAILURE);

    }

 

    // Get the NewPerson function.

    Person_creator* NewPerson = (Person_creator*)dlsym(lib_handle, "NewPerson");

    if (!NewPerson) {

        exit(EXIT_FAILURE);

    }

 

    // Get the NewPersonWithName function.

    PersonWithName_creator* NewPersonWithName = (PersonWithName_creator*)dlsym(lib_handle, "NewPersonWithName");

    if (!NewPersonWithName) {

        exit(EXIT_FAILURE);

    }

 

    // Get the DeletePerson function.

    Person_disposer* DeletePerson =

        (Person_disposer*)dlsym(lib_handle, "DeletePerson");

    if (!DeletePerson) {

        exit(EXIT_FAILURE);

    }

 

    // Create Person objects.

    Person* person1 = NewPerson();

    char person_name[] = "Cendrine";

    Person* person2 = NewPersonWithName(person_name);

    cout << "[" << __FILE__ << "] person1->name() = " << person1->name() << "\n";

    cout << "[" << __FILE__ << "] person2->name() = " << person2->name() << "\n";

 

    // Use Person objects.

    char person1_name[] = "Floriane";

    person1->set_name(person1_name);

    cout << "[" << __FILE__ << "] person1->name() = " << person1->name() << "\n";

    char person2_name[] = "Marcelle";

    person2->set_name(person2_name);

    cout << "[" << __FILE__ << "] person2->name() = " << person2->name() << "\n";

 

    // Destroy Person objects.

    DeletePerson(person1);

    DeletePerson(person2);

 

    // Close the library.

    if (dlclose(lib_handle) != 0) {

        exit(EXIT_FAILURE);

    }

 

    return 0;

}