여러분도 알다시피 64 비트 Windows에서는 이름이 장식되어 있지 않습니다.
32 비트 __cdecl
및 __stdcall
기호에서 기호 이름 앞에 밑줄이 표시됩니다. 예제 함수의 32 비트 버전에 대한 내 보낸 이름의 후미 '@ 8'은 매개 변수 목록의 바이트 수입니다. 당신이 __stdcall
을 지정했기 때문에 거기에 있습니다. __cdecl
호출 규칙 (C/C++ 코드의 기본값)을 사용하면 알 수 없습니다. 그럼 그냥
pfnConnect = GetProcAddress(hDLL, DecorateSymbolName("Connect"));
pfnOtherFunc = GetProcAddress(hDLL, DecorateSymbolName("OtherFunc"));
또는 이와 유사한 (오류가 예를 생략 검사)로 전화
#if _WIN64
#define DecorateSymbolName(s) s
#else
#define DecorateSymbolName(s) "_" ## s
#endif
: 당신이 __cdecl
를 사용하는 경우, 그것은 훨씬 쉽게와 같은 뭔가 GetProcAddress()
을 포장 할 수 있습니다. 개발 과정에서 내 보낸 함수 변경의 서명, 당신은 당신의 #define
주위에 나사를하지 않는 경우에, 더 쉽게 유지 관리 할 수있을뿐 아니라
__declspec(dllexport) long __cdecl Connect(char * name, long size);
__declspec(dllexport) long __cdecl OtherFunc(int someValue);
: 이렇게하려면로 내 보낸 함수를 선언 기억 포장지.
단점 : 개발 중에 지정된 함수의 매개 변수 목록에있는 바이트 수가 변경되면 서명을 변경해도 이름이 변경되지 않으므로 함수를 가져 오는 응용 프로그램에서 캐치되지 않습니다. 개인적으로, 나는 이것이 문제라고 생각하지 않는다. 왜냐하면 이름이 장식되어 있지 않기 때문에 64 비트 빌드가 같은 상황에서 폭발하기 때문이다. 응용 프로그램이 올바른 버전의 DLL을 사용하는지 확인해야합니다.
DLL 사용자가 C++을 사용하는 경우 C++ 기능을 사용하여보다 나은 방법으로 항목을 래핑 할 수 있습니다. 명시 적으로로드 된 전체 라이브러리를 래퍼 클래스로 래핑 할 수 있습니다 (예 :) :
class MyDLLWrapper {
public:
MyDLLWrapper(const std::string& moduleName); // load library here
~MyDLLWrapper(); // free library here
FARPROC WINAPI getProcAddress(const std::string& symbolName) const {
return ::GetProcAddress(m_hModule, decorateSymbolName(symbolName));
}
// etc., etc.
private:
HMODULE m_hModule;
// etc.
// ...
};
실제로 이와 같은 래퍼 클래스로 할 수있는 일은 훨씬 많습니다. 편집에
: OP는 의견의 PInvoke를 사용하여 언급하기 때문에 - 사람이 작업을 수행하기로 결정하면, 는 PInvoke를 사용시 [DllImport]
선언에 CallingConvention = CallingConvention.Cdecl
을 추가을 잊지 마세요. __cdecl
은 관리되지 않는 C/C++의 기본값 일 수 있지만 관리되는 코드의 기본값은 아닙니다.
그래서 내가 올바르게 이해한다면 나는 이것을 dll-projects에 추가하면된다. 내 응용 프로그램과 DLL을 사용하는 C# PInvokes가 변경없이 작동합니까? 그렇다면이 솔루션에 대한 단점이 다른 제안 된 솔루션과 비교하여 있습니까? – dbostream
알겠습니다. 입력 해 주셔서 감사합니다. – dbostream
@dbostream : 순수 C 인터페이스가있는 함수를 기본 C++ DLL에서 내보내려면 .DEF 파일을 사용하여 _undecorated_ 함수 이름을 얻는 것이 편리합니다. –