동일한 이름의 함수를 제공하는 두 개의 라이브러리가있는 경우 어떻게해야합니까?
vorbis_...
, sf_...
, sdl_...
). 이것은 본질적으로 C ++가 네임 스페이스 함수의 심볼 이름에 대해 수행하는 작업입니다.
동일한 이름의 함수를 제공하는 두 개의 라이브러리가있는 경우 어떻게해야합니까?
vorbis_...
, sf_...
, sdl_...
). 이것은 본질적으로 C ++가 네임 스페이스 함수의 심볼 이름에 대해 수행하는 작업입니다.
답변:
주석에 대한 제안 : "내보내기"란 라이브러리에 연결된 모듈을 볼 수 있도록하는 것을 의미합니다 extern
. 파일 범위 의 키워드 와 동일합니다 . 이것이 제어되는 방법은 OS 및 링커에 따라 다릅니다. 그리고 그것은 제가 항상 찾아봐야하는 것입니다.
다음을 사용하여 개체 파일의 기호 이름을 바꿀 수 있습니다. objcopy --redefine-sym old=new file
(man objcopy 참조)를 .
그런 다음 새 이름을 사용하여 함수를 호출하고 새 개체 파일과 연결합니다.
Windows에서는 LoadLibrary () 를 사용 하여 이러한 라이브러리 중 하나를 메모리에로드 한 다음 GetProcAddress () 를 사용 하여 함수 포인터를 통해 함수를 호출하고 호출해야하는 각 함수의 주소를 가져올 수 있습니다.
예 :
HMODULE lib = LoadLibrary("foo.dll");
void *p = GetProcAddress(lib, "bar");
// cast p to the approriate function pointer type (fp) and call it
(*fp)(arg1, arg2...);
FreeLibrary(lib);
foo.dll에서 bar라는 함수의 주소를 가져 와서 호출합니다.
나는 유닉스 시스템이 유사한 기능을 지원한다는 것을 알고 있지만 그 이름은 생각할 수 없습니다.
dlopen
dlsym
, 및 dlclose
. 그러나 Unix에서의 캡슐화는 Windows만큼 효과적이지 않을 수 있습니다.
여기에 생각이 있습니다. 16 진 편집기에서 문제가되는 라이브러리 중 하나를 열고 문제가되는 모든 문자열을 다른 것으로 변경하십시오. 그러면 이후의 모든 호출에서 새 이름을 사용할 수 있습니다.
업데이트 : 나는 방금 이것을 끝냈고 작동하는 것 같습니다. 물론 나는 이것을 철저히 테스트하지 않았습니다. hexedit 산탄 총으로 다리를 날려 버리는 좋은 방법에 지나지 않을 것입니다.
Linux를 사용한다고 가정하면 먼저 추가해야합니다.
#include <dlfcn.h>
예를 들어, 적절한 컨텍스트에서 함수 포인터 변수를 선언하십시오.
int (*alternative_server_init)(int, char **, char **);
https://stackoverflow.com/a/678453/1635364에 명시된 Ferruccio와 같이 , 실행하여 사용하려는 라이브러리를 명시 적으로로드합니다 (좋아하는 플래그 선택).
void* dlhandle;
void* sym;
dlhandle = dlopen("/home/jdoe/src/libwhatnot.so.10", RTLD_NOW|RTLD_LOCAL);
나중에 호출하려는 함수의 주소를 읽으십시오.
sym = dlsym(dlhandle, "conflicting_server_init");
다음과 같이 할당 및 캐스팅
alternative_server_init = (int (*)(int, char**, char**))sym;
원본과 비슷한 방식으로 전화하십시오. 마지막으로 다음을 실행하여 언로드합니다.
dlclose(dlhandle);
함께 사용하지 마십시오. 내가 올바르게 기억하면 링커는 그러한 경우 오류를 발행합니다.
나는 시도하지 못했지만, 해결책이있을 수 있습니다 dlopen()
, dlsym()
그리고 dlclose()
어떤 프로그래밍 동적 라이브러리를 처리 할 수 있습니다. 두 함수가 동시에 필요하지 않은 경우 두 번째 라이브러리 / 함수를 사용하기 전에 첫 번째 라이브러리를 열고 첫 번째 함수를 사용하고 첫 번째 라이브러리를 닫을 수 있습니다.
.o 파일이있는 경우 여기에 좋은 대답이 있습니다. https://stackoverflow.com/a/6940389/4705766
요약:
objcopy --prefix-symbols=pre_string test.o
.o 파일의 기호 이름을 바꾸려면 또는
objcopy --redefine-sym old_str=new_str test.o
.o 파일에서 특정 기호의 이름을 바꿉니다.이 문제는 C ++에 네임 스페이스가있는 이유입니다. 동일한 이름을 가진 2 개의 타사 라이브러리에 대한 c에는 실제로 훌륭한 솔루션이 없습니다.
동적 객체 인 경우 공유 객체 (LoadLibrary / dlopen / etc)를 명시 적으로로드하고 해당 방식으로 호출 할 수 있습니다. 또는 동일한 코드에서 동시에 두 개의 lib가 필요하지 않은 경우 정적 링크로 작업을 수행 할 수 있습니다 (.lib / .a 파일이있는 경우).
물론 이러한 솔루션은 모든 프로젝트에 적용되지 않습니다.
저주? 내가 아는 한, 동일한 이름의 링크 포인트를 노출하는 두 개의 라이브러리가 있고 둘 모두에 대해 링크해야하는 경우 할 수있는 일이별로 없습니다.
그들 중 하나에 래퍼 라이브러리를 작성해야합니다. 래퍼 라이브러리는 고유 한 이름의 기호를 노출해야하며 고유하지 않은 이름의 기호는 노출하지 않아야합니다.
다른 옵션은 헤더 파일에서 함수 이름을 바꾸고 라이브러리 오브젝트 아카이브에서 심볼의 이름을 바꾸는 것입니다.
어느 쪽이든, 둘 다 사용하려면 해킹 작업이 될 것입니다.
질문은 10 년이 다가오고 있지만 항상 새로운 검색이 있습니다.
이미 답변했듯이 --redefine-sym 플래그가있는 objcopy는 Linux에서 좋은 선택입니다. 예를 들어 https://linux.die.net/man/1/objcopy를 참조하십시오. 전체 문서는 를 . 변경하는 동안 기본적으로 전체 라이브러리를 복사하고 모든 업데이트를 수행하려면이 작업을 반복해야하기 때문에 약간 복잡합니다. 그러나 적어도 작동해야합니다.
Windows의 경우 라이브러리를 동적으로로드하는 것이 해결책이며 Linux의 dlopen 대안과 같은 영구적 인 것입니다. 그러나 dlopen () 및 LoadLibrary () 모두 유일한 문제가 중복 이름 인 경우 피할 수있는 추가 코드를 추가합니다. 여기서 Windows 솔루션은 objcopy 접근 방식보다 더 우아합니다. 링커에게 라이브러리의 심볼이 다른 이름으로 알려져 있다고 말하고 해당 이름을 사용하십시오. 그것을하기위한 몇 가지 단계가 있습니다. def 파일을 만들고 EXPORTS 섹션에 이름 번역을 제공해야합니다. 참조 https://msdn.microsoft.com/en-us/library/hyx1zcd3.aspx를 (VS2015, 그것은 결국 새로운 버전으로 교체 얻을 것이다) 또는 http://www.digitalmars.com/ctg/ctgDefFiles.html(아마 더 영구적 인) def 파일의 전체 구문 세부 정보를 보려면. 프로세스는 라이브러리 중 하나에 대한 def 파일을 만든 다음이 def 파일을 사용하여 lib 파일을 빌드 한 다음 해당 lib 파일과 링크하는 것입니다. (Windows DLL의 경우 lib 파일은 코드 실행이 아닌 링크에만 사용됩니다.) .dll 파일과 헤더 파일이있을 때 .lib 파일을 만드는 방법을 참조하십시오. 을 빌드하는 프로세스에 대해서는 . 여기서 유일한 차이점은 별칭을 추가하는 것입니다.
Linux 및 Windows의 경우 이름이 별칭이 지정되는 라이브러리 헤더의 함수 이름을 바꿉니다. 작동해야 할 또 다른 옵션은 새 이름을 참조하는 파일에서 #define old_name new_name, 내보내기가 별칭이 지정된 라이브러리의 헤더를 #include 한 다음 호출자에 #undef old_name을 포함하는 것입니다. 라이브러리를 사용하는 파일이 많은 경우 더 쉬운 대안은 정의, 포함 및 정의 해제를 래핑하는 헤더를 만든 다음 해당 헤더를 사용하는 것입니다.
이 정보가 도움이 되었기를 바랍니다.
dlsym, dlopen, dlerror, dlclose, dlvsym 등을 사용한 적이 없지만 man 페이지에서 libm.so를 열고 cos 함수를 추출하는 예제를 제공합니다. dlopen은 충돌을 찾는 과정을 거치나요? 그렇지 않은 경우 OP는 두 라이브러리를 수동으로로드하고 라이브러리가 제공하는 모든 기능에 새 이름을 할당 할 수 있습니다.