2010-08-16 3 views
8

this question에 따르면 은 C++/CLI를 사용하여 관리 코드와 비 관리 코드를 완벽하게 결합 할 수 있습니다. 나는 그것을 얻지 못한다. 어쨌든 관리되는 것과 관리되지 않는 것 사이에 마샬링이 없어야 하는가?C++ 코드가 C++/CLI에서 호출 될 때 마샬링은 어떻게 수행됩니까?

예를 들어 InnerLibrary는 InnerLibrary의 코드를 호출하는 헤더 및 C++/CLI OuterLibrary가있는 네이티브 C++ .dll로 컴파일됩니다. 마샬링이 있을까요? 누가 그것을 구현할 것이고 비용이 얼마나 드는가?

답변

3

C++/CLI가 전화를 직접 보내는 안전하지 않은 코드를 낼 수 있기 때문에 마샬링 할 필요가 없습니다. Reflector에서 C++/CLI 코드를 살펴 보겠습니다. C#과 매우 다르게 보일 것입니다.

이것은 C#이 수행 할 수없는 것입니다 (최소한 unsafe 키워드 및 일부 포인터 해킹이 없으면). 또한 순수 모드 C++/CLI가 수행 할 수없는 것입니다 (C#).

.NET 안전하지 않은 코드는 관리되지 않는 함수를 직접 호출 할 수 있습니다. C++/CLI를 통하는 경우를 제외하고는이 기능을 편리하게 사용할 수 없다는 것입니다.

+0

나는 그것을 얻지 않는다. 누군가가 C# 코드에서 OuterLibrary를 호출하려고합니다 (그리고 OuterLibrary는 내부적으로 InnerLibrary를 호출합니다). 그는 화성하지 않고 일할 수 있습니까? – sharptooth

+0

@sharptooth : 내부적으로 'InnerLibrary'를 호출하는 접근성있는 public 메소드를 생성하는 경우에만. C + +/CLI조차도 마샬링이 항상 겉으로 드러나는 것은 아니라는 나의 대답을보십시오. – Abel

+0

@sharptool, C++/CLI를 사용하면 스스로 마샬링 코드를 효과적으로 작성하고 있습니다. –

3

마샬링은 관리되지 않는 데이터 또는 관리되는 세계를 호출하는 프로세스입니다. 단지 — 일 뿐이므로 — 사이의 번역을 말하십시오.

Withing C++/CLI를 사용하면 혼합하고 일치시킬 수 있습니다. 즉, * .h 파일을 사용하고 전통적인 C++ 코드를 사용하여 직접 라이브러리를 사용하는 경우 관리되지 않고 마샬링되지 않습니다. BCL 클래스 나 자체 관리 코드를 사용하여 해당 데이터에 액세스하는 경우 필요한 경우에만 마샬링 계층을 수동으로 추가합니다. 즉, LPTSTR은 관리 문자열로 변환되어 하나로 사용되어야합니다. C++/CLI를 사용하면 안전하고 검사 된 관리 코드를 사용하지 않고이 단계를 건너 뛰고 기존의 C++ 코드를 그대로 사용하여보다 빠르고 관대 한 코드를 작성할 수 있습니다.

0

관련된 데이터 유형에 따라 다릅니다.

내장 유형은 int, double 등 (string가 필요하지 않음)로 네이티브에서 같은 표현을 가지고 코드를 관리, 더 마샬링이 필요하지 않습니다. 내장 타입의 배열도 같은 방법으로 배치됩니다 (.NET 저장소는 메타 데이터를 무시하지만 배열 내용과 별개입니다).

모든 멤버가 내장 유형 인 명시 적 레이아웃 속성을 사용하는 값 ​​유형도 메모리 레이아웃과 호환됩니다.

데이터가 관리되는 힙의 개체에 저장되는 경우 고정되어 있어야합니다 (모든 배열에서 마찬가지입니다).

반면에 클래스 유형은 앞뒤로 변환/변환되어야합니다.

+0

'int','double' 등이 박스 화되어 있다면 내부 표현은 * 네이티브 C++ 버전과 다릅니다. – Abel

+0

아니요. 메타 데이터 헤더가 추가되었지만 값의 표현은 변경되지 않으므로 기본 코드는 값을 고정하지 않고 마샬링없이 직접 값을 읽고 쓸 수 있습니다. –

2

마샬링이 사용되지만 사용자 (즉, 프로그래머)가 명시 적으로 처리해야합니다.

당신의 C++ CLI OuterLibrary가 호출하는 경우

System.String/ System::String^을 소요하는 기능을 가진다는 C++ 타입 시스템을 사용하면 const char* 취하는 InnerLibrary 함수에 전달하기 전에 타입 변환을 수행해야합니다. 당신은 스스로 전환을해야합니다 - 그것은 마샬링입니다.

마이크로 소프트는 C++ < -> C++ CLI 상호 작용에 도움이되는 기능을 제공하는 C++ Support Library이라는 것을 제공합니다.

0

여기 두 지점이 있습니다

1) 관리/관리되지 않는 코드 전환 : 모든 전환의 고정 비용을 가지고있다. C++/CLI 코드가 단일 어셈블리에서 컴파일 될 때 컴파일러는 가능한 경우 모든 코드를 관리하여 이러한 전환을 최소화하려고합니다. C++/CLI 코드에서 외부 관리되지 않는 Dll을 호출하면 이러한 최적화가 불가능합니다. 따라서 적어도 시간이 결정적인 섹션에서는 이러한 전환을 최소화하는 것이 좋습니다. 자세한 내용은 여기 http://msdn.microsoft.com/en-us/magazine/dd315414.aspx, 성능 및 상호 운용성 경계의 위치

2) 매개 변수 마샬링. 매개 변수 유형에 따라 다릅니다. 일부 매개 변수는 마샬링 될 필요가 없습니다 (예 : int와 같은 간단한 유형). 문자열은 마샬링되어야합니다. 포인터를 고정하는 것과 같은 몇 가지 트릭을 사용하면 간단한 유형 배열 마샬링을 방지 할 수 있습니다.

5

글쎄, C++/CLI 컴파일러에 내장 된 기능으로 C++ Interop입니다. 당신이 생각할 수있는 흑 마술이 훨씬 적습니다. JIT 컴파일러는 C++ 컴파일러가 생성하는 것과 동일한 종류의 기계 코드를 생성합니다. 모든 .NET 값 유형은 C++에서 직접적으로 동등하므로 변환이 필요하지 않습니다. 이 아니고이 참조 유형을 자동으로 처리하지 않으면 직접 처리해야합니다. pin_ptr <>, 일반적으로.

모두 정말로은 관리 스택 프레임에서 관리되지 않는 스택 프레임으로의 전환을 처리하는 코드를 삽입합니다. 이 코드는 가비지 컬렉터가 인식하는 스택에 특별한 "쿠키"를 저장합니다. 이를 통해 관리되지 않는 프레임에 실수가 발생하지 않도록하고 관리되지 않는 포인터를 개체 참조로 잘못 식별합니다. 이 코드에는 그리 많은 것이 없으며 릴리스 빌드에서 약 5 나노초 정도 걸립니다.

+1

'KeyValuePair '은 값 유형이지만 직접 해당하는 것은 없습니다. 값 유형은 모든 멤버가 레이아웃 호환 (내장 유형 또는 다른 레이아웃 호환 값 유형) 인 경우 레이아웃 호환 가능합니다. –