2013-07-18 5 views
4

재 진술 질문을 찾을 수는 :C++ 리눅스 : (아직 해결 됐어요 있지만) dlopen을가 .so를 라이브러리

나는 문제가 dlopen을 사용하는 데 봤는데 (3) 리눅스의 공유 객체 라이브러리를로드합니다. 라이브러리는 나에 의해 구축 된 라이브러리 시스템의 일부이며 런타임에는 중앙 실행 파일로로드됩니다. 이 모든 작업은 Code :: Blocks의 단일 작업 공간으로 구성되어 있습니다. 각 작업에는 프로그램과 함께 제공 될 Source라는 디렉토리 내에 자체 폴더가 있습니다. 실행 파일의 빌드 디렉토리는 exectuable과 Source 폴더가 동일한 디렉토리에 있도록 자신의 소스 코드에서 두 개의 디렉토리입니다. 라이브러리도 실행 파일과 동일한 디렉토리에 빌드되므로 당연히 라이브러리의 이름을 전달합니다 나는 같이 열려고 해요 :

int main(int argc, char** argv) { 
    void* hLibrary = dlopen("libLibrary.so", RTLD_NOW | RTLD_GLOBAL); 
    if(hLibrary == NULL) { 
     fprintf(stderr, "%s\n", dlerror()); 
     return 1; 
    } 

    return 0; 
} 

빌드 디렉토리가 소스 코드와 같은 살 때 위에서 설명한 배열에 주위에 소스 코드의 디렉토리를 변경할 때까지이 한 지점에서 일하고 있었다. 이 문제는 dlerror()가 파일이 명확하게 존재하고 실행 파일과 동일한 디렉토리에 있더라도 "libLibrary.so를 열 수 없습니다 : 해당 파일이나 디렉토리가 없습니다"를 반환한다는 점입니다. dlopen (3)의 맨 페이지에 따르면 /를 추가하면 상대 디렉토리를 나타 내기 때문에 "/libLibrary.so"를 대신 전달하려고했습니다. 동일한 오류가 반환되었습니다.

이 해결책은 "./"이 필요하다는 것입니다. 여기서 "." 은 실행 파일의 작업 디렉토리를 나타내며, Code :: Blocks에서 실행 파일을 빌드 할 위치로 변경해야하는 작업 디렉토리를 나타냅니다. 완벽하게 다음 작품 :

void* hLibrary = dlopen("./libLibrary.so", RTLD_NOW | RTLD_GLOBAL); 

이 정말 전체 솔루션을 표시하지 않지만, 다음은 기본적으로 내가 뭘하는지하는 것과 동일합니다 :

void* hLibrary = dlopen("./../../libLibrary.so", RTLD_NOW | RTLD_GLOBAL); 

가 희망이 상황을 조금 설명 보다 나은.

답변

9

는 (컴퓨터에 터미널에 man dlopen을 입력하여 예)를 dlopen(3) 맨 페이지를 읽어

은 파일 이름이 다음이 A (상대 또는 절대로 해석됩니다 슬래시 ("/")를 포함하는 경우) 경로명. 그렇지 않으면, 라이브러리의 동적 링커 검색은 다음과 같이 (ld.so (8) 에 대한 자세한 내용을 참조)

o (ELF only) If the executable file for the calling program 
     contains a DT_RPATH tag, and does not contain a DT_RUNPATH tag, 
     then the directories listed in the DT_RPATH tag are searched. 

    o If, at the time that the program was started, the environment 
     variable LD_LIBRARY_PATH was defined to contain a colon-separated 
     list of directories, then these are searched. (As a security 
     measure this variable is ignored for set-user-ID and set-group-ID 
     programs.) 

    o (ELF only) If the executable file for the calling program 
     contains a DT_RUNPATH tag, then the directories listed in that 
     tag are searched. 

    o The cache file /etc/ld.so.cache (maintained by ldconfig(8)) is 
     checked to see whether it contains an entry for filename. 

    o The directories /lib and /usr/lib are searched (in that order). 

그래서 그냥 dlopen("libLibraryName.so", RTLD_NOW)에 플러그인을 원하는 -not dlopen("./libLibraryName.so", RTLD_NOW)를 호출해야 귀하의 $LD_LIBRARY_PATH/usr/lib/ 등 .... - 또는 LD_LIBRARY_PATH.을 추가하십시오 (보안상의 이유로 권장하지 않음).

Jhonnash answered로서 당신은 사용 dlopen (또는 dlsym)가 실패 할 때 dlerror의 결과를 표시해야합니다

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

당신은 일반적으로 리눅스 시스템 프로그래밍에 대한 지식을 얻을 Advanced Linux Programming 같은 책을 읽어보십시오.

+1

나는이 질문을하기 전에 실제로이 페이지를 읽었습니다. 저를 얻은 것은 "상대적인 것 또는 절대적인 것"이었습니다 (그들은 반대의 ... 어느 쪽인가요?). 그리고 어디에도 "." 대부분의 경우 윈도우에서 프로그래밍을 해왔으므로 일반 이름,/앞에는 /, 이름 앞에는 ./의 차이를 실제로 알지 못합니다. 고쳐 줘서 고마워. – NmdMystery

+0

한 가지 - 그래도 dlopen이 이름 앞에 "./"이 없으면 어떻게 발견 되었습니까? 그것은 라이브러리와 심볼을 모두 잘 찾아 냈습니다. (또한 "."이 작업 디렉토리라는 것을 알았습니다. Windows 용으로 사용했기 때문에 절대로 사용하지 않아도되었습니다.) – NmdMystery

+1

Linux는 Windows가 아닌 Unix 시스템입니다. 따라서 Windows 습관을 생각하지 마십시오. –

2

dlopen에 대해 정의됩니다. 동적 라이브러리 dlopen 오류는 checked. 일 수 있습니다. 정의되지 않음 기호 error by link.