2014-10-31 2 views
2

많은 시간 동안의 연구 끝에 나는 아무 것도 발견하지 못했습니다. 그래서 나는 해결책을 얻기 위해 좋은 사람들을 찾습니다. 나는 C++로 봇을 쓸 예정이며, 어느 시점에서 그것을위한 플러그인 시스템을 만들고 싶습니다. 이제는 스크립트 언어를 작성할 수 있다는 것을 알았지 만, API를 작성하고 런타임에 동적으로 프로그램 링크를 가질 수 있다는 것을 알고 있습니다. 내 질문은, 어떻게 그 역동적 인 연결을 (어떻게 hexchat 플러그인에 대한) 가지고 있나요? 어떤 우아한 해결책이나 전형적인 디자인에 관한 이론이 있습니까?플러그인 시스템 작성 중입니까?

리눅스 및 POSIX 시스템에서
+1

플러그인 시스템에는 _one_ 프로토콜이 없습니다. 응용 프로그램의 요구에 따라 런타임에 클래스 팩토리/로더 모듈 세트를 작성하고 동적 라이브러리에서 코드를로드해야합니다 (어떤 hexchat인지, 플러그인과 어떻게 작동하는지 모릅니다). 사실, 당신의 질문은 대답하기에는 너무 광범위합니다 (그러나 여전히 WinAPI LoadLibrary와 Linux API dlopen을 살펴보고 그 주위에 무언가를 만드는 것을 고려하십시오). 투표를 종료합니다. – utnapistim

+1

C로 태그를 추가 했으므로 GLibs [GModule] (https://developer.gnome.org/glib/stable/glib-Dynamic-Loading-of-Modules.html)를보고 [GTypeModule] (https :// /developer.gnome.org/gobject/stable/GTypeModule.html) 자동 인터페이스 로딩이있는보다 정교한 버전입니다. – jku

+0

나는 당신의 질문을 이해하지 못했습니다. 나는 대답을했다. –

답변

3

, 당신은 dlopen(3) & dlsym (이러한 기능 등 GTK, Qt, POCO에서 예를 들어, Glib를 ... 포장 또는 일부 라이브러리)을 사용하고 싶습니다. 더 정확하게,

는 플러그인으로 position independent code 공유 라이브러리를 구축 :

gcc -fPIC -Wall -c plugin1.c -o plugin1.pic.o 
gcc -fPIC -Wall -c plugin2.c -o plugin2.pic.o 

공지 플러그인이 C로 코딩되어있는 경우 ++ 당신은 g++로 컴파일거야, 그리고 피하기 위해 extern "C"로 플러그인 함수를 선언해야 name mangling.

그런 다음 당신은 (플러그인은 GNU 작성한 Readline 원하는 경우 위 명령의 끝에서, 예를 들어 -lreadline)을 동적 라이브러리를 추가 할 수 있습니다

gcc -shared -Wall plugin1.pic.o plugin2.pic.o -o plugin.so 

로 플러그인을 연결합니다.

마지막으로 주 프로그램에서 전체 경로와 함께 dlopen으로 전화하십시오.

void* dlh = dlopen("./plugin.so", RTLD_NOW); 
if (!dlh) { fprintf(stderr, "dlopen failed: %s\n", dlerror()); 
      exit(EXIT_FAILURE); }; 

그런 다음 함수 포인터를 얻을 수 dlsym을 사용하여 (자주 dlh글로벌 데이터입니다).

typedef int readerfun_t (FILE*); 

일부 (보통) 전역 함수 포인터를

readerfun_t* readplugfun; 

을 선언하고 처리하는 플러그인에 dlsym를 사용하여 같은 일부 헤더에 자신의 서명은 프로그램 및 플러그인 코드가 모두 포함 선언한다 dlh :

readplugfun = (readerfun_t*) dlsym(dlh, "plugin_reader"); 
if (!readplugfun) { fprintf (stderr, "dlsym failed: %s\n", dlerror()); 
        exit(EXIT_FAILURE); }; 

물론 플러그인 소스 코드 (예 : plugin1.cc)에서

을 정의 할 것입니다.
extern "C" int plugin_reader (FILE*inf) { // etc... 

플러그인에서 일부 생성자 (또는 소멸자) 함수를 정의 할 수 있습니다 (GCC function attributes 참조). the dlopen (또는 dlclose) 시간에 호출됩니다. C++에서는 정적 객체 만 사용하면됩니다. (그들의 생성자는 dlopen 시간에 호출되며, 소멸자는 dlclose 시간에 호출되므로 함수 속성의 이름). 실제로 프로그램 호출

dlclose(dlh), dlh = NULL; 

의 끝에서

, 당신은 dlopen 통화의 많은 (아마도 만 달러) 할 수 있습니다.

일반적으로 메인 프로그램을 -rdynamic에 연결하여 심볼을 플러그인에서 볼 수있게하려고합니다.

gcc -rdynamic prog1.o prog2.o -o yourprog -ldl 

Program Library HowTo & C++ dlopen mini HowTo & Drepper's paper: How to Write a Shared Library 가장 중요한 부분이 정의하는 것입니다

문서에게 플러그인 규칙 (즉, "프로토콜")을 읽고, 즉에 (함수의 집합 (및 API)입니다 be dlsym -ed)이 필요하며이를 사용하는 방법, 호출 순서, 메모리 소유권 정책 등이 있습니다. 비슷한 플러그인을 여러 개 허용하는 경우 메인 프로그램에 잘 문서화 된 후크가있을 수 있습니다. dlsym의 모든 기능을 호출합니다. 관련 dlopen -ed 플러그인. 예 : GCC plugins conventions, GNU make modules, Gedit plugins, ...