2009-08-13 3 views
14

C++/CLI 포인터를 네이티브 C++ 포인터로 변환하는이 문제를 해결했습니다. Heres the background : C++/CLI를 사용하여 Windows 양식 응용 프로그램을 작성하고 있습니다. 응용 프로그램은 여러 COM 인터페이스를 호출합니다. 는 COM 인터페이스를 통해 개체의 (A C++/CLR 클래스의 내부) 인스턴스를 생성 할 때, 내가 같이 CoCreateInstance에 마지막 인수로 (void**)(&provider) 전달 :C++/CLI 포인터에서 네이티브 C++ 포인터로 변환

HRESULT CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)(&provider)); 
그러나

, 내가 컴파일러 오류가 발생합니다 : cli::interior_ptr<Type>에서 void **으로 변환 할 수 없습니다. 나는 이것에 대해 som 연구를 해왔고, C++과 C++/CLI에서 포인터의 다른 유형의 문제 인 것처럼 보입니다. 누구나 이것에 대한 지식이 있으며, 해결 방법에 대한 팁이 있습니까? 고맙습니다!

먼저 모든 도움을 주셔서 감사합니다!

Freich가 제안한대로 pin_ptr을 사용하려고했지만 컴파일러가 interior_ptr에서 pin_ptr으로 변환하는 데 문제가 있다고 불평했습니다. 내가 대신과 interior_ptr를 사용하려고하면 :

pin_ptr<void *> pinnedPtr = &provider; 
CoCreateInstance(CLSID_MSPRProvider, NULL, CLSCTX_LOCAL_SERVER, IID_IMSPRProvider, (void**)pinnedPtr); 

나는 interior_ptr에서 interior_ptr로 변환 할 수 없습니다 얻을. 이 모든 것은 interior_ptrvoid**으로 변환하는 문제로 귀결됩니다. 이와 같이 : (void**)interiorPtr, 여기서 interiorPtrinterior_ptr입니다. 이것에 대한 아이디어가 있습니까?

답변

10

포인터를 관리 된 코드에서 '고정 된'것으로 표시 한 다음 관리되지 않는 메모리 영역에 바이트를 복사 한 다음 해당 포인터를 사용해야한다고 생각합니다. 내가 얻을 수있어 얼마나

std::string managedStringToStlString(System::String ^s) 
{ 
    Encoding ^u8 = Encoding::UTF8; 
    array<unsigned char> ^bytes = u8->GetBytes(s); 
    pin_ptr<unsigned char> pinnedPtr = &bytes[0]; 
    return string((char*)pinnedPtr); 
} 

참고 : 예를 들어, 여기에 UTF-8로 인코딩 된 관리되지 않는 표준 : : 문자열 관리 시스템 :: 문자열에 대한 포인터로 변환 한번 어딘가에있어 코드의 조각이다 배열 bytes에 대한 '고정 된'포인터는 GetBytes() 함수에 의해 반환 된 다음 char*으로 캐스팅 한 후 std::string 생성자에 전달합니다. 이것은 STL 문자열에 바이트를 복사하는 동안 관리되는 메모리 하위 시스템이 bytes 배열을 메모리로 옮기는 것을 피하기 위해 필요하다고 생각합니다.

는 귀하의 경우에는,

pin_ptr<void *> pinnedPtr = &provider; 
CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)pinnedPtr); 

CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)(&provider)); 

를 교체 시도하고 그 작동 여부를 참조하십시오.

+0

이것은 위험한 것 같습니다! 비슷한 (또는 같은) 상황이 발생했습니다 : 고정 된 포인터를 생성하고 네이티브 포인터를 반환했습니다 (함수처럼). 그러나 함수가 끝나고 고정 된 포인터가 삭제 되었기 때문에 개체가 이동되었으므로 개체가 더 이상 필요하지 않습니다. 고정되어 있으며 네이티브 포인터가 유효하지 않습니다! 이것은 디버깅하는 동안 보일 수도 있고 보이지 않을 수도 있지만, 기대하지 않을 때 릴리스 버전에서 발생합니다. –

+0

@TobiasKnauss'std :: string :: string (const char *)'생성자는 참조 된 데이터의 복사본을 생성하므로 함수가 종료 될 때 참조 된 메모리가 더 이상 고정되지 않아도됩니다. –

3

C++/CLI를 사용하는 것은 꽤 오래되었지만 포인터를 고정해야한다고 생각합니다.

+0

수 있도록 설계로 무엇 OP 요구 될 수있는 편의 템플릿라고 CLI :: pin_ptr이에 관리 객체에 대한 포인터가 가비지 수집기에서 이동하지 않습니다. –

3

CoCreateInstance() 호출 이외의 유효한 것으로 예상되는 메모리가 있습니까?

Frerich와 Achim이 말했듯이, 메모리를 옮길 염려없이 포인터를 "고정"하고 내부 포인터를 가져 와서 메모리에 대한 원시 포인터를 얻을 수 있습니다. 일반적으로 이것을 pin_ptr 템플릿으로 처리합니다 (예를 들어 Frerich 게시 참조).

그러나 pin_ptr은 의도적으로 스택에서만 사용할 수 있습니다.멤버 변수 나 전역 변수로 사용할 수 없으므로이를 인수 또는 반환 값으로 전달할 수 없습니다. 메모리는 범위를 벗어날 때 고정 해제됩니다.

따라서 메모리가 CoCreateInstance() 호출 중에 만 유효해야한다면 pin_ptr이 최선의 방법입니다. 당신은 메모리의 복사본을 가지고 을 통과해야합니다 다음하지 않으면 그에 CoCreateInstance를()

관련 문제