티스토리 뷰

프로그래밍/MFC

DCOM 구조체 사용

에어버스 2017. 5. 23. 12:14

https://translate.googleusercontent.com/translate_c?act=url&depth=1&hl=ko&ie=UTF8&prev=_t&rurl=translate.google.co.kr&sl=en&sp=nmt4&tl=ko&u=https://www.codeproject.com/Articles/916/Using-User-Defined-Types-in-COM-ATL&usg=ALkJrhi2amihbBiVjS8vZ04qc9DibAqhgw

wire_marshal 없이 구조체 사용하기(CodeGuru 참조) - http://petra.tistory.com/1089

 

http://www.drdobbs.com/control-how-com-marshals-your-data/184416483  (구글번역)

COM의 약속 중 하나는 COM 개체가 더 현명한 존재가 아닌 클라이언트가 동일한 주소 공간 (DLL을 통해), 다른 프로세스 또는 심지어 원격 컴퓨터의 프로세스에 상주 할 수 있다는 것입니다. 물론 COM 객체가 호출자와 동일한 주소 공간에 있지 않으면 함수 호출 매개 변수를 별도의 주소 공간이나 네트워크를 통해 이동해야하는 문제를 처리해야합니다. 표준 솔루션은 COM 인터페이스를 Microsoft Interface Definition Language (MIDL) 파일로 설명하고 MIDL 컴파일러가 함수 호출 데이터를 압축하여 별도의 또는 원격 프로세스 인 마샬링이라는 프로세스로 보내는 데 필요한 코드를 생성하도록합니다 

그러나 MIDL 컴파일러는 모든 상상할 수있는 데이터 형식을 마샬링하는 방법을 알지 못합니다. 새로운 COM 인터페이스를 설계하는 대부분의 프로그래머는 IDL (Interface Definition Language)로 설명 할 수있는 데이터 유형을 고수 할 것이지만 레거시 코드 또는 특수 상황은 IDL이 처리 할 수없는 데이터 유형을 지시하기도합니다. MIDL 컴파일러의 또 다른 단점은 모든 상황에 대해 최적의 코드를 생성 할 수 없다는 것입니다. 다행히도 IDL을 사용하면 데이터가 마샬링되는 방식을 정확하게 제어 할 수 있습니다. 이는 인터페이스 정의 파일 (IDL)wire_marshal 속성을 사용하여 수행됩니다. 데이터를 마샬링하는 방법을 제어하면 IDL 파일에 완벽하게 설명 할 수없는 데이터 유형을 마샬링 할 수 있으며 데이터의 즉석 압축 및 압축 해제와 같은 다른 기능을 구현할 수 있습니다 

이 기사에서는 wire_marshal 특성과 일부 애플리케이션을 설명합니다. 다음 예제에서는 wire_marshal 을 사용하여 클라이언트에서 out-of-process COM 서버로 전달되는 데이터의 압축 을 구현합니다. 이는 특히 서버가 잠재적으로 느린 네트워크 링크를 통해 연결된 다른 컴퓨터에있을 때 유용합니다. wire_marshal을 사용하면 큰 이점 중 하나는 클라이언트와 서버간에 데이터가 전송되는 방식을 정의 할 수 있다는 것입니다. 이를 통해 데이터 전송 방식을 완벽하게 제어하면서 애플리케이션 코드, 인터페이스 및 데이터 구조를 간단하고 손쉽게 사용할 수 있습니다 

마샬링 소개  

프로세스가 동일한 프로세스 또는 다른 프로세스에있는 COM 프로세스의 메소드를 호출 할 때 메소드에 전달 된 매개 변수는 두 개의 주소 공간 사이에서 전송되어야합니다. 매개 변수를 전송하려면 대상 프로세스에 전송할 수있는 단일 메모리 블록으로 직렬화해야합니다. 전송 메커니즘은 대상 프로세스가 원본과 동일한 시스템에 있으면 로컬 원격 프로 시저 호출 (LRPC)이거나 다른 시스템에있는 경우 원격 프로 시저 호출 (RPC) 일 수 있습니다. 매개 변수를 serialize하고 역 직렬화하는 프로세스를 마샬링이라고합니다 

프로세스 A가 문자열 포인터를 매개 변수로 전달하여 프로세스 B에있는 객체에서 메소드를 호출하는 상황을 생각해보십시오. 이 포인터는 B를 처리 할 의미가 없으며 사용 된 경우 액세스 위반을 트리거합니다 (또는 나쁜 경우 B의 주소 공간에서 임의의 데이터를 가리 킵니다). 대신 문자열을 사용하기 전에 문자열을 프로세스 B의 주소 공간에 복사해야합니다. 마샬링 프로시 저는 문자열을 RPC 하위 시스템이 대상 프로세스로 전송하는 메모리 블록에 복사합니다. 그런 다음 문자열은 대상 프로세스의 주소 공간에있는 메모리 블록에복사되고 메서드에 전달 된이 메모리에 대한 포인터입니다 

프로세스간에 데이터를 마샬링하는 책임은 프록시 및 스텁 DLL이라고합니다. out-of-process 개체에 대한 호출이있을 때마다 COM에 의해 자동으로로드됩니다. 이러한 DLL을 개발하고 배포하는 책임은 COM 서버 개발자에게 있습니다. 클라이언트는 클라이언트에 대해 아무것도 모릅니다. 그림 1 은 모든 구성 요소 간의 관계를 보여줍니다 

프록시 및 스텁 코드는 일반적으로 각 프로세스 공간에 별도로로드되는 동일한 DLL에 있습니다. DLL을 작성하는 작업은 Microsoft IDL 컴파일러 (MIDL)IDL 파일을 읽고, 컴파일 할 때 .c .h 파일 세트를 생성하여 매우 단순화됩니다.이 파일은 프록시 / 스텁 DLL을 생성합니다. 다음은 두 개의 매개 변수 (문자열 및 구조체)를 사용하는 하나의 메소드로 간단한 인터페이스를 정의하는 샘플 IDL 파일입니다 

typedef struct {
int iDay;
int iMonth;
int iYear;
} DATE;

[
Object,
uuid (c15c5681-e9db-11cf-a683-0020af4357e3),
]

interface ISimple : IUnknown
{
import "unknwn.idl";
import "oaidl.idl";
HRESULT SetUserDetails ([in] LPSTR pszUserName, [in] 날짜 * pDateOfBirth);
}

IDL 컴파일러에서 생성 된 코드에는 ISimple_SetUserDetails_Proxy () ISimple_SetUserDetails_Stub () 라는 두 개의 함수가 포함됩니다. 프록시 함수는 모든 매개 변수를 보유 할 수있을만큼 큰 메모리 블록을 할당하고 매개 변수를 메모리 블록에 복사 한 다음 RPC를 사용하여이 블록을 스텁에 전달합니다. 스텁은 매개 변수를 추출하고 필요한 모든 메모리를 할당하며 실제 매개 변수를 실제 SetUserDetails () 메서드에 전달합니다. 실제 SetUserDetails () 메서드가 반환되면 스텁 코드는 매개 변수에 할당 된 모든 메모리를 해제합니다.

프록시 / 스텁 코드를 작성하는 마지막 작업은 필요할 때로드하는 방법을 알 수 있도록 COM에 등록하는 것입니다. 관련 프록시 / 스텁이있는 각 구성 요소에는 아래의 정의에 키 "ProxyStubClsid32"키가 추가됩니다.

HKEY_CLASSES_ROOT\ 인터페이스\ [clsid]

  로드 할 올바른 프록시 / 스텁 DLL을 식별합니다.

  마샬링, IDL 파일 및 프록시 / 스텁 등록에 대한 전체 설명을 보려면 Inside OLE Kraig Brocksmidt Inside COM 에서 Dale Rogerson이 읽는 것이 좋습니다. 두 가지 모두 Microsoft Press에서 게시합니다.

  wire_marshal 속성

  wire_marshal 속성은 IDL 컴파일러에 특정 데이터 유형에 특별한 마샬링이 필요하며 마샬링에 도움이되는 추가 코드를 제공한다는 것을 알려주는 IDL 키워드입니다. 일반적으로 데이터 유형을 IDL 파일에 완전히 설명 할 수 없거나 데이터를 원래 형식으로 마샬링 할 수없는 경우에 사용됩니다.

  wire_marshal 의 좋은 예는 클라이언트가 HBITMAP 을 매개 변수로 서버에 전달하는 경우입니다. 비트 맵 핸들은 클라이언트 프로세스 외부에서 의미가 없으며 HBITMAP IDL에서 마샬링하는 방법을 알고있는 데이터 유형이 아닙니다. wire_marshal을 사용하면 마샬링 프로세스에 개입하고 비트 맵을 서버로 전송하기 위해 버퍼로 압축하는 클라이언트 측 코드와 비트 맵을 재구성하고 서버 프로세스에서 유효한 HBITMAP 을 생성하는 서버 측 코드를 제공 할 수 있습니다. 이 사용자 지정 마샬링 코드는 클라이언트 호출 코드와 서버에서 호출되는 COM 개체와 독립적입니다. 사실 COM 개체의 클라이언트가 동일한 프로세스가 아니라 개체가 원격인지 여부를 결정하기 란 어렵습니다. Microsoftwire_marshal을 사용하여 표준 IDL 파일에서 HBITMAP에 마샬링을 제공합니다. 이 창과 다른 표준 창 유형에 대한 정확한 정의는 wtypes.idl 파일에서 찾을 수 있습니다. (Visual C ++의 경우 \ include \ wtypes.idl , Borland C ++의 경우 \ sdktools \ rpc \ wtypes.idl 을 참조하십시오.)

  내 샘플 코드는 wire_marshal 속성을 사용하여 클라이언트에서 다른 프로세스 / 시스템에있는 서버로 전달되는 BOOL 배열을 압축합니다. 배열은 비트 필드로 압축되어 하나의 바이트 에 8 개의 BOOL 을 전송할 수 있습니다. 서버 측에서이 비트 필드를 다시 BOOL 배열로 변환합니다. 클라이언트와 서버 어느 쪽도이 압축 및 압축 해제가 발생하고 있음을 알지 못하므로 응용 프로그램 코드가 데이터를 전송할 때 최대의 효율성을 보장하면서 편리한 데이터 표현을 사용할 수 있습니다. 클라이언트가 일부 하드웨어에 대한 상태 정보를 초당 몇 번씩 서버로 전송하는 모니터링 프로세스라고 상상하면 압축을 구현할 때의 이점을 알기 시작할 수 있습니다.

  wire_marshal 사용하기

  데이터 유형에 대해 wire_marshal을 구현 하는 첫 번째 단계는 IDL 파일에 wire_marshal 속성 을 사용하여 데이터 유형을 선언하는 것입니다. 이렇게하려면 먼저 데이터에 대한 와이어 표현을 정의해야합니다. 이것은 마샬링 한 데이터가 어떻게 전송 될지를 나타냅니다. 절대 요구 사항은 아니지만 와이어 유형 정의가 데이터 구조의 실제 표현임을 강력히 권장합니다. 이렇게하면 와이어 유형 정의를 IDL 파일의 다른 정의에 포함시킬 수 있습니다. 그런 다음 wire_marshal 특성을 사용하여 와이어 형식을 마샬링 할 실제 데이터 형식과 연결합니다. 다음은 sobj.idl에서 추출한 내용입니다 ( 목록 1 ).

  typedef struct {
short szie;
[size_is (size)] unsigned char * pData;
} wireCOMPARR;
typedef [unique] wireCOMPARR * LPCOMPARR;
typedef [wire_marshal (LPCOMPARR)] void * LPMYARRAY;

여기서는 먼저 데이터를 전송하는 데 사용할 와이어 데이터 형식 ( wireCOMPARR )을 정의합니다. 이것은 2 바이트 크기 필드와 압축 된 부울 데이터를 포함 할 바이트 배열에 대한 포인터로 구성되는 구조입니다. IDL 코드 추출의 마지막 행은 와이어 포인터 유형 LPCOMPARR 을 데이터 유형 LPMYARRAY 와 연관시킵니다 . 이것은 IDL 컴파일러에게 LPMYARRAY의 데이터 유형을 만날 때마다 LPCOMPARR 유형으로 데이터 유형을 마샬링 및 언 마샬링하는 사용자 제공 마샬링 코드를 호출해야한다고 알려줍니다.

sobj.idl의 나머지 부분 ( 목록 1 )BOOL s ( LPMYARRAY )의 배열에 대한 포인터를 매개 변수로 취하는 단일 메서드 DisplayArray () 를 포함하는 ISimpleObject 인터페이스를 정의합니다. IDL 파일에 나타날 수있는 모든 BOOL 포인터의 마샬링을 제어하고 싶지 않기 때문에 BOOL * 또는 LPBOOL 대신 LPMYARRAY 유형을 사용했습니다.이 특정 매개 변수 만 (특정 크기라는 것을 알고 있습니다). 그래서이 함수의 인수에 대해 고유 한 typedef 를 작성하여 wire_marshal 특성을이 특정 BOOL * 매개 변수에만 적용 할 수 있습니다.

와이어 데이터 형식을 정의하고 wire_marshal 특성을 사용하여 제어 할 마샬링이있는 데이터 형식과 연결하려면 네 가지 기능을 작성해야합니다. 이러한 함수는 데이터의 크기 조정, 마샬링 및 비 정렬 화를 처리하고 비 정렬 화 프로세스 중에 할당 된 메모리를 해제합니다. 함수는 나머지 MIDL 생성 코드와 연결되어 프록시 / 스텁 DLL을 형성합니다. 필요한 기능은 다음과 같습니다.

<type> _UserSize ()
<type> _UserMarshal ()
<type> _UserUnmarshal ()
<type> _UserFree ()

여기서 <type> wire_marshal 속성으로 선언 한 데이터 유형입니다. marshal.c ( Listing 2 )에는 BOOL 배열을 마샬링하기 위해 작성한 네 가지 함수가 들어있다.

<type> _UserSize ()

이 함수는 데이터가 마샬링을 준비 중이며 프록시 프로토 타입에서 호출되며 다음 프로토 타입이 있습니다.

unsinged long __RPC_USER <type> _UserSize (
ULONG __RPC_FAR * pFlags, ULONG StartingSize,
<type> __RPC_FAR * pUserObject);

IDL로 생성 된 프록시 코드는 전달되는 모든 매개 변수를 수용 할 수있을만큼 큰 메모리 블록을 할당합니다. 이 함수는 데이터가 차지할 공간이 얼마나되는지 확인하기 위해이 함수를 호출합니다.

첫 번째 매개 변수는 COM에 의해 전달 된 플래그 집합을 포함합니다. 1 은 해당 플래그에 대한 정의를 보여줍니다. 플래그의 윗부분은 기계 별 데이터 특성을 지정합니다. 하반부는 마샬링이 일어나고있는 상황 (: 다른 컴퓨터의 서버)을 코드에 알려줍니다. 이 플래그를 사용하면 컨텍스트에 따라 마샬링 코드의 동작을 변경할 수 있습니다. 필자는 다른 컴퓨터로 정렬 할 때 BOOL 배열 만 압축하기로 결정할 수있었습니다.

두 번째 매개 변수에는 이전 매개 변수로 인해 마샬링 버퍼에 필요한 바이트 수가 포함됩니다. 이 함수의 반환 값은 마샬링 버퍼에 필요한 새로운 바이트 수이므로 계산할 크기에이 두 번째 매개 변수를 추가해야합니다.

세 번째 매개 변수는 마샬링 할 개체에 대한 포인터입니다. marshal.c ( Listing 2 )LPMYARRAY_UserSize ()는이 특정 데이터 유형이 고정 크기 (256 BOOL s)를 가지기 때문에이 매개 변수가 필요하지 않습니다.

반환 값은 마샬링 될 때의 데이터 크기와 전달 된 startingSize 매개 변수의 값이어야합니다. 실제로 마샬링 할 때까지 데이터의 정확한 크기를 결정할 수없는 경우 필요한 크기의 초과 추정치를 반환합니다. 전송 된 데이터의 크기는 마샬링 후 버퍼의 할당 크기가 아닌 데이터 크기에 의해 결정됩니다.

<type> _UserMarshal ()

이 함수는 호출 측 RPC 코드가 제공 한 버퍼로 데이터를 마샬링하기 위해 프록시 측에서 호출됩니다. 그것은 다음과 같은 프로토 타입을 가지고 있습니다 :

unsigned char __RPC_FAR * __RPC_USER <유형> _UserMarshal (
ULONG __RPC_FAR * pFlags,
ULONG __RPC_FAR * pBuffer,
<type> __RPC_FAR * pUserObject);

첫 번째 인수는 <type> _UserSize ()에 전달 된 동일한 플래그 집합을 포함합니다. 1 은 다양한 비트를 설명합니다.

두 번째 인수는 마샬링 할 데이터를 복사해야하는 버퍼에 대한 포인터입니다. 물론 필요한 바이트 수를 복사 할 수는 있지만 예상되는 <type> _UserSize () 함수보다 많은 바이트를 복사해서는 안됩니다.

세 번째 인수는 마샬링을 요청하는 데이터에 대한 포인터입니다. marshal.c ( 목록 2 )LPMYARRAY_UserMarshal ()은 여덟 개의 BOOL 값을 단일 바이트로 묶 습니다. 또한 wire_type 정의가 마샬링 된 데이터의 실제 레이아웃과 일치해야한다는 것을 기억해야합니다.

반환 값은 버퍼에 마샬링 된 데이터 뒤의 첫 번째 바이트의 주소 여야합니다. 그냥 전달 된 버퍼 포인터에 사용 된 바이트 수를 추가하십시오.

<type> _UserUnmarshal ()

이 함수는 스텁 측에서 호출되어 데이터가 호출되는 함수로 전달되기 전에 데이터를 원래 형식으로 비 정렬 화합니다. 그것의 원형은 :

unsigned char __RPC_FAR * __RPC_USER <유형> _UserUnmarshal (
ULONG __RPC_FAR * pFlags, ULONG __RPC_FAR * pBuffer,
<type> __RPC_FAR * pUserObject);

이 함수는 <type> _UserMarshal () 과 동일한 매개 변수를 사용합니다. , 버퍼 ( pBuffer )가 이제 프록시 측에서 복사 된 데이터를 가리키는 반면 pUserObject 는 비 정렬 화 된 데이터를 받아야하는 데이터 객체를 가리 킵니다.

이 함수는 마샬링 된 데이터 다음의 첫 번째 바이트 여야하는 RPC 버퍼의 새 위치에 대한 포인터를 반환해야합니다.

pUserObject 포인터에서 반환 할 메모리를 할당하는 방법에 특히주의해야합니다. 예를 들어 대상 함수가이 포인터를 COM 또는 MAPI 코드로 전달하면 적절한 COM 또는 MAPI 메모리 할당 메커니즘을 사용해야합니다. 샘플 코드는 CoTaskMemAlloc () COM 함수를 사용하여 해당 메모리를 할당합니다.

<type> _UserFree ()  

이 함수는 <type> _UserUnmarshal () 에서 할당 한 메모리를 해제하기 위해 스텁 측에서 호출됩니다. 인터페이스 메소드에 대한 호출이 완료되면 스텁 코드는이 함수를 호출하여 메모리를 비울 수 있습니다.

  첫 번째 인수는 표 1에 설명 된 친숙한 플래그 집합입니다. 두 번째 인수는 <type> _UserUnmarshal ()이 초기화 된 객체에 대한 포인터입니다. 이 샘플에서는 CoTaskMemFree () 를 사용하여 LPMYARRAY_UserUnmarshal () 에서 CoTaskMemAlloc () 호출로 할당 된 메모리를 해제합니다.

  프록시 / 스텁 DLL 빌드

  4 가지 기능은 일반적으로 IDL 컴파일러가 생성 한 소스와 함께 빌드 된 별도의 .c 파일에 배치되어 프록시 / 스텁 DLL을 만듭니다. marshal.c ( Listing 2 ) 파일은 샘플에 필요한 네 가지 함수를 구현한다. 프록시 / 스텁 DLL을 빌드하려면 IDL 파일에서 MIDL 컴파일러를 실행하여 프록시 / 스텁 DLL의 코드를 생성하십시오. 파일을 사용자 마샬링 코드에 포함시켜 빌드하십시오. 마지막 단계는 필요할 때 COM을로드하는 방법을 알 수 있도록 프록시 / 스텁 DLL을 레지스트리에 등록하는 것입니다. register.c ( 목록 3 )는 샘플 인터페이스에 필요한 레지스트리 설정과 함께 필요한 레지스트리 설정을 보여줍니다.

  프록시 / 스터브 DLL 외에 wire_marshal 특성을 설명하기 위해 간단한 클라이언트 응용 프로그램 및 서버 응용 프로그램을 만들었 습니다. marsamp.h ( Listing 4 )에는 프로젝트 헤더 파일 client.cpp ( Listing 5 )에는 콘솔 기반 클라이언트 애플리케이션이 들어 있고 server.cpp ( Listing 6 )에는 콘솔 기반 서버 애플리케이션이 들어있다. makefile ( 목록 7 )에는 프로젝트를 빌드하는 nmake 지시문이 들어 있습니다. 이번 달의 코드 아카이브에는 완전한 소스 코드가 포함되어 있습니다.

  샘플 클라이언트 프로그램 ( client.exe )BOOL 값의 256 요소 배열을 COM 서버 ( server.exe )에 전달하여 전달합니다. 또한 클라이언트는 데이터를 일관성있게 검사 할 수 있도록 서버에 전달하기 전에 배열을 표시합니다. 사용자 지정 마샬링 코드는 전송 전후에 배열을 압축하고 압축을 해제합니다. 서버 프로그램은 정상 및 압축 된 데이터 크기를 모두 표시합니다.

  샘플 빌드 및 실행

  샘플 소스는 Visual C ++ v5.0을 사용하여 빌드되었습니다. 샘플을 빌드하고 실행하려면 다음을 수행하십시오.

  1. nmake 를 실행하여 프로젝트 파일을 빌드하십시오. 이렇게하면 클라이언트 인 client.exe 가 빌드됩니다. server.exe , 서버; sobj.dll , 프록시 / 스텁 DLL.

  2. 다음 명령 줄을 사용하여 서버를 실행하여 서버 및 프록시 / 스텁 DLL을 등록합니다.

  server-register [서버 및 프록시 / 스텁 위치 경로]

  서버와 프록시 / 스텁 DLL은 같은 디렉터리에 있어야합니다. 이것은 내가 작성한 등록 코드에만 기인하며 일반적인 COM 요구 사항은 아닙니다.

  3. client.exe 를 실행하십시오. ISimpleObject 인스턴스가 만들어져 서버가 실행됩니다.

  4. "-unregister"를 매개 변수로 사용하여 server.exe를 실행하여 서버 및 프록시 / 스텁 DLL의 등록을 취소 할 수 있습니다.

  여러 시스템에서 샘플 실행

  클라이언트와 다른 시스템에서 서버를 실행하려면 다음을 수행하십시오.

  1. server.exe sobj.dll 을 서버 시스템에 복사하십시오.

  2. 서버 시스템에서 이전 단계 2를 반복하십시오.

  3. server.exe 를 실행하십시오. 출력을 보려면이 작업을 수행해야합니다. 서버 프로그램은 "Waiting ..."문자열을 표시하고 클라이언트가 연결을 기다리고 앉아 있습니다.

  4. 클라이언트 시스템에서 client.exe 를 실행하고 서버 시스템 이름 만 매개 변수로 전달하십시오.

  두 시스템에서 DCOM을 활성화해야합니다. dcomcnfg.exe 프로그램을 사용하여이를 확인하고 서버에 대해 올바른 액세스 권한을 사용할 수 있도록 할 수 있습니다. DCOMCNFG가 표시하는 등록 된 개체 목록에 "ISimpleObject - WDJ wire_marshal 예제"라는 항목이 표시됩니다. 이 버튼을 두 번 클릭하면 개체에 대한 액세스 권한이 표시되며 필요한 경우 변경할 수 있습니다.

  프록시 / 스텁 코드 디버깅

  프록시 / 스텁 DLL의 코드를 디버깅 할 때 OLE RPC 디버깅을 사용하도록 설정해야합니다. Visual C ++"디버그"탭 아래에있는 "옵션"대화 상자에서이 작업을 수행 할 수 있습니다. 또한 COM에 의해로드 될 때까지는 프록시 / 스텁 DLL의 소스에 중단 점을 설정할 수 없습니다. 이것은 프록시 / 스텁이 등록 된 객체를 처음 만들 때 발생합니다. DLL이로드되면 해당 소스에서 중단 점을 설정할 수 있습니다.

  개요

  wire_marshal 속성을 사용하면 프로세스 또는 기계 경계를 통과 할 때 데이터가 표현되는 방식을 정확하게 정의 할 수 있습니다. 또한 특수 마샬링 코드를 사용하는 상위 계층에서 숨겨진 한 곳에서 마샬링 코드를 찾을 수 있으므로 응용 프로그램 코드와 인터페이스를 가능한 간단하게 유지할 수 있습니다. 이 기사에서 사용 된 압축 / 압축 해제 예제는 많은 용도 중 하나 일뿐입니다. 다른 용도로는 전송하기 전에 중복 정보를 완전히 제거하고 IDL 파일에서 올바르게 정의 할 수없는 리소스 또는 데이터 구조에 대한 핸들과 같이 네이티브 형식으로 마샬링 할 수없는 데이터를 마샬링하는 방법이 있습니다.

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28