프로그래밍2007.09.04 23:22
Lex 와 Yacc 설명
http://dinosaur.compilertools.net/
http://www.therobs.com/uman/lexyacc.shtml

Flex와 Bison의 다운로드 링크만 있는데 Lex, Yacc FAQ(http://www.therobs.com/uman/faq.shtml)를 보면

Flex and Bison are essentially compatible GNU versions of Lex and Yacc. Flex also supports C++ class generation and actions.

Flex와 Bison은 Lex, Yacc의 GNU 버전과 본질적으로 호환됩니다. Flex 역시 C++ 클래스 생성과 활용도 지원합니다.

Flex와 Bison의 Win32 포팅은 Wilbur Streett 라는 사람이 해놓았습니다.

http://www.monmouth.com/~wstreett/lex-yacc/lex-yacc.html

가면 다운받을 수 있습니다.

추가로 lex, yacc 예제를 http://memphis.compilertools.net/interpreter.html 에 가면 볼 수 있습니다.
Posted by 꿍스
TAG lex, yacc
생각2007.08.08 23:43
효율적인 블로그를 위하여 이글루스로 블로그를 옮겼다.

하루하루 나 자신에 대해 반성하고 되돌아봐야 하는데 그러기 위해 블로그가 낫다는 생각을 하게되었다.

매일매일은 쓰지못하더라도 조금식 나에대해 글을 쓰도록 해보자.
Posted by 꿍스
미디어2007.08.08 23:37
싱클레어는 신앙과 지성이 조화된 분위기 속에서 부모님아래에서 성장했다. 그의 가정은 말 그대로 밝은 세계이며 선의 세계이다. 또한 그 주위에 있는 아주 어두운 악의 세계를 발견하게 된다. 싱클레어의 어린 시절 그는 동네 놀이 집단에 끼기 위해 도둑질을 했다는 허풍을 프란츠 크로머에게 떨게된다. 어두운 세계에 눈을 뜨게 된 것이다. 어두운 생활을 하던 싱클레어는 데미안을 만나게 된다. 데미안을 통해서 카인과 아벨이라는 새로운 해석으로 선과 악을 생각하게 되고, 데미안은 크로머를 만나 싱클레어를 옭아맨 올가미를 풀어준다.

싱클레어는 자기 자신 속의 두 세계의 갈등으로 즉, 금지된 것과 허락된 것의 사이에서 심한 갈등을 겪고 있다. 베크는 그런 싱클레어를 술집으로 유혹한다. 뒷골목의 어두운 모습, 시궁창의 풍경은 금지된 구역에 들어서게 되고 자기 소외와 자기 부정에 빠져 사회와 이사에 대해 아예 부정해 버린다. 그는 베크와 함께 카인과 아벨 신화의 이중성, 성의 금욕주의, 연애감정에 대해 생각한다. 다시 데미안을 만나고 데미안은 싱클레어의 타락한 모습에 우려를 나타낸다. 싱클레어는 정신이 성을 갈망하는 육체를 통제하지 못하여 괴로워한다.

싱클레어는 베아트리체를 만나면서 자기 자신의 내부에서 일어 소용돌이치는 마음에 따라 그런 곳에서 벗어나게 된다. 싱클레어가 그녀의 초상화를 그린다. 그가 그린 초상화는 데미안을 닮아가고 있었다. 베아트리체가 아닌 남성적이면서 여성적인 모습으로 변하여 마침내 데미안의 모습으로 변해가고 있었던 것이다. 그는 그 안에서 어느새 데미안을 그리워하고 있다.

싱클레어는 지구에서 날아오르려고 하는 새를 그려 데미안에게 보낸다. 그리고 데미안으로부터 편지 한 통이 도착한다. 더 나은 세계를 향해 날아가는 새, 먼저의 세계를 파괴하고 나온 새, 그리고 신 아프락사스에 관한 이야기이다. 아프락사스는 빛과 어두움의 공존, 선신이면서 동시에 악신이라는 것을 싱클레어는 알게 된다. 그는 데미안의 편지를 통해서 자기 내부의 자신을 발견하게 된다.

오르간 소리에 이끌려 싱클레어가 어느 교회로 들어간다. 그 곳에서 그는 연주자 피스토리우스를 만나서 아프락사스에 대한 공감을 느끼고, 그에게 아프락사스에 대한 가르침도 받게 된다. 싱클레어는 정신을 이끌어 줄 지도자와 같은 사람이 필요하다. 데미안을 길에서 다시 만난다. 데미안은 그의 어머니와 함께 있다. 싱클레어와 데미안의 재회. 싱클레어는 데미안의 어머니 에바 부인이 자신의 내부에 존재하고 있는 여인상이라는 것을 깨닫는다. 그녀는 꿈, 운명, 탄생의 괴로움을 알려 준다. 싱클레어는 그녀에게 정신적인 사랑과 육체적인 사랑을 같이 느끼게 되고 정신적인 사랑으로 생각한다.

그 때 전쟁이 터지고 데미안과 싱클레어는 함께 참전한다. 싱클레어는 부상을 당하고 야전병원으로 옮겨지게 된다. 데미안과 싱클레어가 나란히 누워 있다. 데미안은 만약 언젠가 자신이 필요하게 되면 싱클레어 스스로의 내면에 귀를 기울이라고 말하고 어머니의 키스를 그에게 전한다.

다음날 아침 데미안은 옆에 없다. 싱클레어는 자신의 내면으로 들어가 친구이며 지도자인 데미안과 꼭 같은 자기 자신의 모습을 본다.

새는 알에서 나오려고 투쟁한다.

알은 세계다.
태어나려는 자는 하나의 세계를 깨뜨려야 한다.


굉장히 유명한 문구고 그만큼 너무도 멋진 문구입니다 ^^

뒤에 "새는 신의 곁으로 날아간다. 그 신의 이름은 아프락사스라 한다"

이 문구가 있는데요 전 그냥 위에 쓴 것만이 좋더라구요


그러나 모든 사람은 누구나 인간을 향해 던져진 자연이다.

이것도 꽤 유명한 문구지요


이거 두개는 일반적으로 유명한 문구이고, 유명한 건 또 생각나는 게 없어서 ;

제가 개인적으로 좋아하는 문구 알려드릴게요 ^^


우리가 어떤 사람을 미워하면, 우리는 그의 모습 속에, 바로 우리들 자신 속에

들어앉아 있는 그 무엇인가를 보고 미워하는 것이지. 우리들 자신 속에 있지 않은 것,

그건 우리를 자극하지 않아.


우리의 과제는 세계 안아에서 하나의 섬을 제시하는 것, 어쩌면 하나의 모범을,

아무튼 살아가는 다른 가능성을 알리는 것이었다. 내가, 오래 고립되어 있던 사람인

내가, 완전히 혼자임을 맛보고 난 사람들 사이에 존재하는 공동체를 알게 되었다.

출처 : 엠파스 검색
Posted by 꿍스
프로그래밍2007.07.24 00:59
각 타입별 이름 짓는 규칙을 표준화된 모니커 인터페이스를 통해서 지을 수 있도록 함

시스템 모니커 종류 : 이름 짓는 객체에 대해 추가의 정보 필요
파일 모니커 : CreateFileMoniker
아이템 모니커 : CreateItemMoniker
포인터 모니커 : CreatePointerMoniker
안티 모니커 : CreateAntiMoniker
복합 모니커 : CreateGenericComposite
클래스 모니커 : CreateClassMoniker
URL 모니커 : CreateURLMoniker
OBJREF 모니커 : CreateObjrefMoniker

커스텀 모니커
IMoniker 인터페이스 구현

IBindCtx ( 바인드 컨텍스트 )
모니커 바인딩 동작에 대한 정보를 가지고 있는 객체

IMoniker::BindToObject ( 바인드 컨텍스트 정보를 인자로 넘겨줌 )
BindMoniker 헬퍼 메소드 ( 바인드 컨텍스트 정보 넘겨주지 않음 )

IMoniker::GetDisplayName 모니커의 디스플레이 이름을 리턴
IMoniker::ParseDisplayName 디스플레이 이름으로 모니커 객체를 가져옴

MkParseDisplayname 함수
원하는 타입의 모니커 객체를 가져옴
IMoniker::ParseDisplayName과 유사하나 모니커가 필요없이 모니커를 가져옴
ProgID:ObjectName 형식의 문자열을 취함 ex : "clsid:{0000-0000{00-00}}"

CoGetClassObject 함수 : 디스플레이 이름의 모니커를 변환하고 이름지어진 객체로 바인딩하는 과정을 단순화 시킴

IClassActivator 인터페이스 : 클래스 모니커의 기본 동작을 가로채서 변경할 수 있도록 해줌.

IMoniker * pClassMoniker;
CreateClassMoniker( clsid , &pClassMoniker);

//////////////////////////////////////////////////////////////

// 바인드 컨텍스트 시작
IBindCtx * pBindCtx;
CreateBindCtx(0, &pBindCtx);

ULONG eaten;
IMoniker * pMoniker;
OLECHAR string[] = L"clsid:00000000-0000-0000-000000000000001";
MkParseDisplayName(pBindCtx, string, &eaten, &pMoniker);

// 모니커에서 클래스 팩토리를 바인딩 한다.
IClassFactory * pClassFactory;
pMoniker->BindToObject(pBindCtx, NULL, IID_IClassFactory, (void**)&pClassFactory);

// 클래스 팩토리로 COM객체를 생성한다.
IUser * pUser;
pClassFactory->CreateInstance(&pUser);

// 무엇을 한다
pUser->Some();

// 모든 것을 헤제한다.
pClassFactory->Release();
pUser->Release();
pBindCtx->Release();
pMoniker->Release();



ROT ( 동작 객체 테이블 )
객체들이 스스로 등록할 수 있는 컴퓨터 단위의 테이블
모니커를 객체에 바인딩 할때, ROT를 통해서 모니커는 객체가 이미 동작중인지를 확인할 수 있다. -> 불필요하게 새로운 인스턴스 생성X

GetRunningObject 함수를 통하여 IRunningObjectTable 인터페이스 를 얻어서 ROT에 등록 하고 해제한다.

// ROT의 모니커이름을 뿌려줌 ////////////////////////
/////////////////////////////////////////////////////////

IRunningObjectTable * pRunningObjectTable;
GetRunningObjectTable(NULL, &pRunningObjectTable);

IEnumMoniker * pEnumMoniker;
pRunningObjectTable->EnumRunning(&pEnumMoniker);

IMoniker * pMoniker;
IBindCtx * pBindCtx;
OLECHAR * moniker_name;

// 모든 모니커에 루프를 돔
while(pEnumMoniker->Next(1, &Moniker, NULL) == S_OK)
{
CreateBindCtx(0, &pBindCtx);

pMoniker->GetDisplayName(pBindCtx, NULL, &moniker_name);
wprintf(L"DisplayName is %s\n", moniker_name);
CoTaskMemFree(moniker_name);

pMoniker->Release();
pBindCtx->Release();
}

pEnumMoniker->Release();
pRunningObjectTable->Release();





MSDN : http://msdn2.microsoft.com/en-us/library/ms688618.aspx ( IMoniker-Class Moniker Implementation )
Posted by 꿍스
프로그래밍2007.07.23 22:21
COM 객체에 영속성을 부여하기 위한 방법

IPersist
COM 객체가 영속성 객체임을 구현

인터페이스를 상속받은 인터페이스
IPersistStream : 스트림 사용
IPersistStreamInit : IPersistStream에서 초기화를 위해 InitNew 메쏘드 추가
IPersistMemory : 스트림 대신에 메모리
IPersistStorage : 스토리지를 사용
IPersistFile : 파일을 사용
IPersistPropertyBag2 : 프로퍼티 백 사용 ( ActiveX 콘트롤 속성값 )
IPersistMoniker : 모니커 사용
IPersistHistory : 사용자 웹사이트 히스토리 저장(익스플로러)
위 인터페이스를 COM 객체에 구현하여 영속성을 부여 함

ATL에서는 위 인터페이스들 중에서 구현 클래스를 제공한다
IPersistStreamInitImpl
IPersistStoreageImpl
IPersistPropertyBagImpl

구현
IPersistStream을 구현할시에 CLSID도 같이 스트림에 저장하고 빼온다
OleSaveToStream, OleLoadFromStream 헬퍼 함수 사용

IStream
IPersistStream, IPersistStreamInit 인터페이스를 구현하는 COM 영속성 객체에 실제로 스트림에 읽거나 쓰는 클라이언트 구현 인터페이스
IPersistStream, IPersistStreamInit 의 Save , Load 메소드의 인자로 IStream 인터페이스가 전달됨

사용 방법
// COM 객체생성
IUnknown * pUnknown;
... CoCreateInstance 중략

// IPersistStreamInit 인터페이스 가져옴
CComPtr <IPersistStreamInit> pPersistStreamInit;
hr = pUnknown->QueryInterface(IID_IPersistStreamInit, (void**)&pPersistStreamInit);

// 메모리 기반 스트림
CComPtr <IStream> pStream;
hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);

// 초기화
hr = pPersistStreamInit->InitNew();

// 객체를 스트림으로 저장
hr = pPersistStreamInit->Save(pStream, TRUE);

// 포인터를 처음으로 옮김
LARGE_INTEGER zero = {0, 0};
hr = pStream->Seek(zero, STREAM_SEEK_SET, NULL);

// 새로운 객체 생성
// IPersistStreamInit 인터페이스를 가져옴

// 스트림에서 객체 가져옴
hr = pPersistStreamInit->Load(pStream);

구현 방법
CreateStreamOnHGlobal : 일반적인 IStream 인터페이스의 구현을 얻음 ( 글로벌 메모리의 블록에 기반한 스트림 객체 생성 ) <-> GetHGlobalFromStream
구조화된 저장 서비스 : 디스크 기반의 파일로 스트림 저장

데이터를 저정하기 위한 표준화 되고 구조적인 형식으로 단일 파일내에 데이터를 저장
IStorage 인터페이스를 이용하여 IStream 인터페이스 객체 생성

// 구조화된 저장소 파일을 생성 하거나 오픈하고 IStorage 인터페이스를 얻어옴
CComPtr IStorage pStorage;
hr = StgCreateStorageEx(L"C:\\test.stg", STGM_DIRECT | STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, STGFMT_STORAGE, 0, 0, IID_IStorage, (void**)&pStorage);

// Stream 객체를 생성하고 IStream 인터페이스를 얻어옴
CComPtr IStream pStream;
hr = pStorage->CreateStream(L"TestStream", STGM_DIRECT | STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream);

// 파일에 데이터를 쓴다.
ULONG bytes_written;
char data[] = "HELLO THERE!";
pStream->Write(data, strlen(data), &bytes_written);

Property ( 속성 )
표준화된 방법 으로 요약정보를 저장하는 데 사용할 수 있는 속성 집합 형식 ( Ex : 파일 요약 정보 )

// IStorage 인터페이스로 IProperySetStorage 인터페이스를 가져옴
CComPtr <IPropertySetStorage> pPropertySetStorage;
pStorage->QueryInterface(IID_IPropertySetStorage, (void*)&pPropertySetStorage);

// IPropertySetStorage 인터페이스를 이용하여 IPropertyStorage 인터페이스 객체 생성
CComPtr <IPropertyStorage> pPropertyStorage;
pPropertyStorage->Create(FMTID_SummaryInformation, NULL, PROPSETFLAG_ANSI, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, &pPropertyStorage);

속성집합을 정의
PROPSPEC(속성구별자 또는 문자열 이름) , PROPVARIANT(속성 값) 구조체 이용

PROPSPEC ps;
ps.ulKind = PRSPEC_PROPID;
ps.propid = PIDSI_AUTHOR;

PROPVARIANT pv;
pv.vt = VT_LPSTR;
pv.pszVal = "Anna";

hr = pPropertyStorage->WriteMultiple(1, &ps, &pv, 0);

MSDN : http://msdn2.microsoft.com/en-us/library/aa380369.aspx (Structured Storage)
Posted by 꿍스
프로그래밍2007.07.22 17:20
타입 라이브러리는 인터페이스 정의의 이진 형식

IDL정의시 library 키워드 사용

타입 라이브러리 생성

// 타입 라이브러리 파일 생성
ICreateTypeLib2 * pCreateTypeLib2;
CreateTypelib2(SYS_WIN32, L"C:\\mylib.tlb",&pCreateTypeLib2);

// 타입 정보 추가
ICreateTypeInfo * pCreateTypeInfoInterface;
pCreateTypeLib2->CreateTypeInfo(L"IUser", TKIND_INTERFACE, &pCreateTypeInfoInterface);

타입 정보 얻기

ITypeLib* pTypeLib;
LoadRegTypeLib(LIBID_User, 1, 0, LANG_NEUTRAL, &pTypeLib);
HRESULT hr = pTypeLib->GetTypeInfoOfGuid(CLSID_UserCOM, &pTypeInfo);
pTypeLib->Release();

ITypeComp
ITypeLib, ITypeInfo를 거칠 필요 없이 타입 라이브러리내의 타입 정보들을 빠르게 찾아낼 수 있다.

자세한 사항은 MSDN : http://msdn2.microsoft.com/en-us/library/ms221398.aspx
Posted by 꿍스
프로그래밍2007.07.22 16:06
인터페이스가 많아지면 규모성의 문제가 생김 -> 특정 인터페이스들을 지원하는 컴포넌트를 카테고리 별로 분류
클라이언트 프로그램은 레지르스트리를 빠르게 검색하여 특정 카테고리를 지원하는 컴포넌트를 구별하여 인스턴스화 함

카테고리 구별자 CATID
HKEY_CLASSES_ROOT > Component Categories
HKEY_CLASSES_ROOT > CLSID

컴포넌트 객체는 Implemented Categories 레지스트리 키를 사용하여 자신이 지원하는 컴포넌트 카테고리들을 알린다.

컴포넌트 객체는 Required Categories 레지스트리 키를 사용하여 자신이 받아들일 수 있는 클라이언트의 카테고리를 알린다.
( 객체에 접근할 수 있는 클라이언트를 매우 제한하여 버리기 때문에 조심해서 사용 )

카테고리의 기본 컴포넌트

TreatAs 레지스트리 키를 이용하여 카테고리의 기본 컴포넌트로 사용할 수 있다.
ToolBoxBitmap32 서브키를 이용하면 OLEViewer 에서 아이콘을 볼수 있다.

클래스 에뮬레이션

코클래스가 발전해나감에 따라 새로운 CLSID를 할당하여 사용하고자 한다면 기존의 CLSID에서 에뮬레이션하여 새로운 CLSID로 연결할 수 있다.
CoTreatAsClass, CoGetTreatAsClass 함수로 에뮬레이션을 설정하거나, 설정된 에뮬레이션 클래스를 가져온다.
이역시 TreatAs 레지스트리 키를 이용 한다.

카테고리 등록
ICatRegister 인터페이스 이용
ComponentCategoryManager를 이용하여 카테고리를 관리한다.

#include // 컴포턴트 카테고리 지원

CATID_USER = {....{ ... }} // UUID

ICatRegister * pCatRegister;
CoCreateInstance(CLSID_StdComponentCategoriesMgr,Null, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void)**&pCatRegister);

CATEGORYINFO catinfo;
catinfo.catid = CATID_USER;
wcsncpy(catinfo.szDescripction, L"사용자",128);

// 등록
pCatRegister->RegisterCategories(1, &catinfo);

// 등록해제
pCatRegister->UnRegisterCategories(1, &CATID_USER);

// 등록, 해제할 컴포넌트 카테고리들
CATID rgcatid[3];
rgcatid[0] = CATID_USER;
rgcatid[1] = CATID_......
rgcatid[2] = CATID_......

// 컴포넌트 카테고리들에 컴포넌트 객체 등록
pCatRegister->RegisterClassImplCategories(CLSID_UserCOM, 3 , rgcatid);
// 컴포넌트 카테고리들에 컴포넌트 객체 해제
pCatRegister->UnRegisterClassImplCategories(CLSID_UserCOM, 3 , rgcatid);

pCatRegister->Release();

카테고리 정보 얻기
ICatInformation 인터페이스 이용
ComponentCategoryManager를 이용하여 카테고리를 관리한다.

ICatInformation * pCatInformation;
CoCreateInstance(CLSID_StdComponentCategoriesMgr,Null, CLSCTX_INPROC_SERVER, IID_ICatInformation, (void)**&pCatInformation);

IEnumCLSID * pEnumCLSID;
pCatInformation->EnumClassesOfCategories(1, &CATID_USER, 0, NULL, &pEnumCLSID);

pCatInformation->Release();

액티브X 컨트롤은 자동으로 ActiveX의 컴포넌트 카테고리로 등록이 된다.

MSDN : http://msdn2.microsoft.com/en-us/library/ms692689.aspx
Posted by 꿍스
프로그래밍2007.07.19 23:54
헬퍼함수는 MSDN색인으로 나오지 않아서 따로 정리 하였습니다.

Variant
오토메이션 호환 타입들의 Union

헬퍼함수
VariantChangeType(Ex)
VariantClear
VariantCopy
VariantCopyInd
VariantInit

ATL 클래스
CComVariant

BSTR
문자열 길이를 접두어로 포함하는 문자열

헬퍼함수
SysAllocString
SysAllocStringByteLen
SysAllocStringLen
SysFreeString
SysReAllocString
SysReAllocStringLen
SysStringByteLen
SysStringLen

ATL클래스
CComBSTR

SafeArray
안전하게 다룰 수 있는 배열

헬퍼함수
SafeArrayAccessData
SafeArrayAllocData
SafeArrayAllocDescriptor(Ex)
SafeArrayCopy
SafeArrayCopyData
SafeArrayCreate(Ex)
SafeArrayCreateVector(Ex)
SafeArrayDestory
SafeArrayDestroyData
SafeArrayDestoryDescriptor
SafeArrayGetDim
SafeArrayGetElement
SafeArrayGetElemsize
SafeArrayGetLBound
SafeArrayGetUBound
SafeArrayLock
SafeArrayPtrOfIndex
SafeArrayPutElement
SafeArrayRedim
SafeArrayUnaccessData
SafeArrayUnlock
SafeArraySetRecordInfo
SafeArrayGetRecordInfo
SafeArraySetIID
SafeArrayGetIID
SafeArrayGetVartype

ATL클래스
CComSafeArray
CComSafeArrayBound

사용자 정의 타입
user-defined type, UDT

구조체에 GUID를 할당 하기 위해 typedef 이용

typedef [ uuid([UUID적음])]
 struct myDataType {
  int x;
  int y;
 } myDataType;

Variant 타입의 VT_RECORD
IRecordInfo 인터페이스 구현

GetRecordInfoFromTypeInfo : 타입정보에서 서술한 UDT의 RecordInfo 얻음
GetRecordInfoFromGuids : uuid 를 통해 UDT의 RecordInfo 얻음

IRecordInfo 포인터를 얻음

IRecordInfo * precordInfo = 0;
hr = GetRecordInfoFromTypeInfo(pTypeInfo, &pRecordInfo);

Posted by 꿍스
프로그래밍2007.07.19 23:18
#include <iostream>
using namespace std;

#include <windows.h>
#include <comdef.h>

void ComCall(VARIANT* pRetVal)
{
enum { ARR_SIZE = 5 };
VariantInit(pRetVal);

short ia[ARR_SIZE] = {5, 6, 7, 8, 9 }; //넘기고자 하는 배열

SAFEARRAYBOUND sab = { ARR_SIZE, 0 };
SAFEARRAY* pSa = SafeArrayCreate(VT_VARIANT, 1, &sab);

_variant_t* _p;
// 만든 SA배열에 포인터를 연결시킴
SafeArrayAccessData(pSa, reinterpret_cast<void**>(&_p));

for (long i = 0; i < ARR_SIZE; i++) {
_p[i] = (long)ia[i];
}

SafeArrayUnaccessData(pSa);

pRetVal->vt = VT_VARIANT | VT_ARRAY;
pRetVal->parray = pSa;

// 위에 두줄을 이렇게 해도 됨
//_variant_t var;
//var.vt = VT_VARIANT | VT_ARRAY;
//var.parray = pSa;
// 꼭 Detach로 넘겨야함 그냥 대입하면 var변수가 메모리가 헤제되버림
// 그럼 *pRetVal 도 같이 메모리 해제되어서 ....
//*pRetVal = var.Detach();
}

int main()
{
_variant_t var;
ComCall(&var);

SAFEARRAY* pSa;

if (var.vt & VT_ARRAY) {
if (var.vt & VT_BYREF)
pSa = *var.pparray;
else
pSa = var.parray;
}
else {
cout << "SafeArray가 아님" << endl;
reutrn 0;
}

long lUBound = 0;
SafeArrayGetUBound(pSa, 1, &lUBound);

_variant_t* _p;
SafeArrayAccessData(pSa, reinterpret_cast<void**>(&_p));

for (int i = 0; i <= lUBound; i++) {
cout << static_cast<long>(_p[i]) << endl;
}

SafeArrayUnaccessData(pSa);

cout << "== END ==" << endl;
cin.get();

return 0;
}


Posted by 꿍스