2010-08-16 6 views
1

어쩌면 어리석은 질문 일지 모르지만 나는 답을 모른다. GetModuleHandle 또는 LoadLibrary를 사용하여 dll을로드 한 다음 (해당 DLL의 함수를 사용하는 경우) 직접 원하는 헤더를 포함하는 것의 차이점은 무엇입니까? 예를 들어, GetModuleHandle 함수 사용하여 :GetModuleHandle과 헤더를 포함한 차이점은

typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); 

// Call GetNativeSystemInfo if supported or GetSystemInfo otherwise. 

PGNSI pGNSI; 
SYSTEM_INFO si; 

ZeroMemory(&si, sizeof(SYSTEM_INFO)); 

pGNSI = (PGNSI) GetProcAddress(
    GetModuleHandle(TEXT("kernel32.dll")), 
    "GetNativeSystemInfo"); 
if(NULL != pGNSI) 
    pGNSI(&si); //calling function through pointer 
else GetSystemInfo(&si); 

하지만를 내가 직접 내 코드에서 해당 함수를 호출 할 WINDOWS.H 헤더를 포함 할 수 있습니다

#include <windows.h> 

SYSTEM_INFO si; 
ZeroMemory(&si, sizeof(SYSTEM_INFO)); 
GetNativeSystemInfo(&si); 

같은 예는 OPENGL32.DLL을 위해, 내가 해달라고 적용 내 프로젝트에 OpenGL 함수의 헤더 파일을 포함 시키거나 Getmodulehandle과 GetProcAdress를 사용하여 원하는 기능을 호출하는 것이 더 좋은지 알고 있습니다. 그 차이점은 무엇입니까? 어떤 방식 으로든 getmodulehandle 혜택을 사용하는 첫 번째 방법은 무엇입니까? 답변 주셔서 감사합니다.

+0

GetNativeSystemInfo()는 특별하기 때문에 사용할 수 없습니다 이전 버전의 Windows. GetProcAddress를 사용해야합니다. 이것은 OpenGL에는 적용되지 않습니다. –

+0

GetNativeSystemInfo()는 예제 일 뿐이지 만 지금은 좋은 예제였습니다. 이제는 이해할 수 있습니다. – sanjuro

답변

6

먼저 등 제 3 자 플러그인을 지원 당신이 GetModuleHandleLoadLibrary 정확히 동일하지 것으로 알고 있습니다 있는지 확인하려면

에서 LoadLibrary도 유용하다. 그러나 이것이 당신의 질문에 직접적으로 포함되지는 않기 때문에 큰 설명을 생략하고 두 링크의 문서를 확실히 이해할 것을 제안합니다.


dll 함수를 다른 함수처럼 직접 사용하려면 헤더 만 포함하면 안됩니다. 헤더 외에도 프로젝트의 어딘가에 해당 lib 파일과 연결하라는 메시지가 전달됩니다. 귀하의 예제에서는 kernel32.lib가됩니다. 이 작업은 프로젝트의 링커 설정 또는 파일에 #pragma comment (lib, ...)이있는 것과 같은 다양한 방법을 통해 수행 할 수 있습니다.

프로그램을 컴파일하면 컴파일러가 코드를 작성하여 프로그램 시작시 해당 DLL을로드합니다. 실제로 프로그램을 실행하려고 할 때 해당 DLL을 찾을 수 없으면 오류 메시지와 함께 실패합니다. 오류를 포착하고 대체 조치를 취할 코드를 작성할 방법이 없습니다.

운영 체제의 일부 (예 : kernel32.dll) 또는 적어도 일반적으로이 DLL과 함께 제공되는 dll의 경우 dll이 항상 존재한다고 가정 할 수 있으므로 즉시 로딩 동작은 문제가되지 않습니다. 반면에, 일반적으로 존재하지 않는 DLL에 대해 빌드하는 경우, 당신은 더 많은 관심을 가질 것입니다. 어느 쪽이든, 그러한 dll이 프로그램과 함께 배포되는지 확인해야합니다. 그렇지 않으면 어떻게 든 사용자가 시스템에 해당 dll을 가져 오는 데 필요한 다른 패키지를 설치하는지 확인해야합니다.

또한 dll이로드되지만 해당 dll에서 사용하려고하는 함수가 실제로 존재하지 않으면 오류 메시지와 함께 즉시 실패합니다. (프로그램이 함수를 호출하려고 시도 할 때까지 기다리지 않고 프로그램이 시작되고 중단 될 때이 불일치를 찾습니다.) dll의 다른 버전이 존재하는 경우 문제가 될 수 있습니다.

이제 LoadLibrary/GetProcAddress를 사용하면 선택한 시간에 dll을로드하고 해당 dll에서 제공하는 특정 기능을 찾으라는 메시지가 표시됩니다. 이러한 단계 중 하나라도 실패하면 합리적인 방법으로 처리하는 코드를 작성할 수 있습니다.

다양한 용도로 사용할 수 있습니다. 예를 들어, 프로그램에서 특정 폴더의 플러그인 dll을 검색하고로드하는 플러그인 메커니즘을 만들 수 있습니다. 프로그램이 어떤 플러그인이 나타날지 미리 알지 못하므로 LoadLibrary가이를 수행하는 유일한 방법입니다.

LoadLibrary/GetProcAddress를 사용할 수있는 또 다른 기능은 dll을로드하고 적절한 헤더 및 lib 파일이없는 경우에도 함수를 호출하는 것입니다. dll의 이름, 함수 이름 및 함수의 정확한 서명 (매개 변수 유형, 반환 유형, 호출 규칙)을 알고 있으면 해당 dll을로드하고 함수를 성공적으로 호출하는 코드를 작성할 수 있습니다. 때때로 이것은 유용 할 수 있습니다. 예를 들어, 사람들이 Windows dll에서 제공하는 "문서화되지 않은"특정 기능을 사용할 수있는 한 가지 방법입니다.

마지막으로 LoadLibrary/GetModuleHandle/GetProcAddress를 사용하면 지원하려는 모든 운영 체제에 반드시 존재하지는 않는 기능을 사용할 수 있습니다. 이는 GetNativeSystemInfo 또는 GetSystemInfo을 호출하는 코드 스 니펫의 원인 인 것으로 보입니다. 전자는 WinXP/2003에서만 사용할 수 있고 후자는 Win2000에서 사용할 수 있습니다. 코드가 GetNativeSystemInfo에 대한 직접 호출로 작성된 경우에는 프로그램이 Windows 2000에서 실행되지 않습니다. 대신에 현재 사용중인 시스템에 GetNativeSystemInfo가 있는지 확인하고 사용하는 경우에만 사용합니다. 그렇지 않으면 더 넓게 지원되는 GetSystemInfo로 대체됩니다.

예를 들어 어떤 함수를 호출할지 선택하는 방법은 지원하려는 운영 체제에 따라 다릅니다. 소프트웨어가 Windows 2000에서 실행될 필요가 없다면 GetNativeSystemInfo를 직접 호출하는 것이 훨씬 쉽습니다.

+0

thxx – sanjuro

1

GetModuleHandle을 사용하면 dll을 동적으로로드 할 수 있으며, 플러그인을 구현하거나 필요에 따라 일부 리소스를로드 할 때 사용할 수 있습니다.
아래에는 두 가지 방법의 차이점이 없습니다. - 정적 라이브러리는 프로그램이 시작될 때 동적 링크를 수행하는 코드를 포함합니다 (C 언어).

+0

헤더 파일을 포함하고 선택적으로 #pragma comment (lib, "opengl32.lib")와 함께 지정할 때 라이브러리 그것은 정적으로 링크 오전 의미합니까? – sanjuro

+0

아니요, (lib,)는 링커가 라이브러리를 찾을 위치를 보여줍니다. 실제로 나는 정적 lib로 dll을 연결하는 것이 가능하다고 생각하지 않습니다. – mbq

+0

@san : OpenGL32.lib에 연결할 때 GetProcAddress를 사용할 필요가 없습니다. 정말 당신이 원하는 무엇입니까, GPL을 사용하여 OpenGL을 꽤 고통 스러울 것입니다. 그리고 불필요한. –

1

다릅니다.이 경우에는 시스템 (kernel32.dll 등)에 바이너리가없는 경우 DLL/exe가 Windows LDR에서 로딩 오류를받지 않도록 사용되는 경우가 있습니다. 일 수도 있습니다.이 좋은 예는 SP 2+에만 존재하는 Windows XP의 DEP 기능이지만 프로그램에 대한 적절한 잠재 고객을 줄이기 위해 필수 SP를 강요하는 것은 바람직하지 않습니다. . OpenGL은 API 지원 (및 확장)을 예측할 수 없다는 사실 때문에 동일한 원리를 사용하기 때문에이를 확인한 다음 가져 오거나 다른 방법으로 가져와야합니다. wglGetProcAddress

또 다른 이유는 'cheap'은 특정 라이브러리에 링크 할 필요가없고 특정 헤더를 포함 할 필요가 없기 때문에 특히 큰 SDK에서 단 1 개의 함수 만 사용하는 경우 다른 개발자가 거대한 SDK를 얻기 위해 시간을 낭비하지 않게됩니다. ofc는 내보내기를 수행하는 바이너리가 필요할 것입니다.)

3

일부 기능은 이전 버전의 Windows에는없고 기능을 직접 호출하면 해당 기능이 프로그램의 가져 오기 테이블에서 종료됩니다. 창에서 가져 오기 테이블의 함수 중 하나를 찾지 못하면 프로그램이 전혀 실행되지 않습니다. 당신이

0

LoadLibraryGetModulehandle 모두 동일한 항목에 대해 작동합니다. 모듈은 런타임에 모듈을 프로세스에 매핑 할 것이지만, LoadLibrary의 경우 커널 관점에서 참조 카운트를 증가시켜 나중에는 그렇게하지 않을 것입니다.

관련 문제