블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2797)
Unity3D (853)
Programming (479)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (185)
협업 (61)
3DS Max (3)
Game (12)
Utility (68)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday

C# C++ COM Interop

Programming/C# / 2011. 11. 15. 14:38

관리되는 코드(C# or C++/CLI) 와 비관리되는 코드(C or C++)이 프로젝트에서 함께 사용되는 경우가 발생한다.
이때 사용되는 기술이 Interop 기술이다.

MSDN : 비관리 코드와의 상호운용

다음 두가지 경우를 생각해보자.

1. C++에서 C# 함수 호출


내용 보기


//-- C# Com Server ---------------------------------------------------------------------//

[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface ICOMClass
{
    void HelloWorld();
}

[ClassInterface(ClassInterfaceType.AutoDual)]
public class COMClass : ICOMClass
{
    ...

    public void HelloWorld()
    {
        MessageBox.Show("Hello");
    }
}

--> 이런 클래스가 있다면 클래스 라이브러리로 컴파일을 하고 C++에서 사용할수 있는 형식라이브러리 생성 및 등록       
      
     regasm COMClass.dll /regfile COMClass.reg
     regasm COMClass.dll /tlb:COMClass.tlb
     참고 : http://msdn.microsoft.com/ko-kr/library/tzat5yw6.aspx

//-- C++ Client -------------------------------------------------------------------------//

[[ Heaer ]]
/** #import attribute
 *        no_namespace : Specifies that the namespace name is not generated by the compiler.
 *        raw_interfaces_only : Suppresses the generation of error-handling wrapper functions and property (C++) declarations that use those wrapper functions
 *        named_guids : Tells the compiler to define and initialize GUID variables in old style, of the form LIBID_MyLibCLSID_MyCoClassIID_MyInterface, andDIID_MyDispInterface.
 **/
#import "COMClass.tlb" no_namespace raw_interfaces_only named_guids

[[ CPP ]]

HRESULT hr;
_COMClassPtr pClass;
hr = pClass->CoCreateInstance(CLSID_COMClass,NULL,CLSCTX_ALL,IID__COMClass,(void**)&pClass);
if(hr != S_OK) return;

ICOMClassPtr pIClass;
pClass->QueryInterface(IID_ICOMClass,(void**)&pIClass);
if(SUCCEEDED(hr))
    pClass->HelloWorld();

잘되었다면.. Hello 메시지 박스를 볼수 있을 것이다. 



2. C# 이벤트를 C++에서 받기

내용 보기


C#의 컨트롤에서 발생하는 이벤트를 C++에서 처리할 경우가 있다.
IDispEventSimpleImpl 를 이용하여 이벤트를 등록하는 방식을 알아보자.

[[ C# ]]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface _EventInterface
    {
        [DispId(1)]
        void ClickedEvent(int ID, bool selected);       
    }
    [ComSourceInterfaces(typeof(_EventInterface))]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    public class VCGraphControl
    {
        [ComVisible(false)]
        public delegate void ClickedEvent(int ID, bool selected);
        public event ClickedEvent ClickEvent;

        // 이벤트발생시
        public function()
        { 
            if(ClickEvent!= null) ClickEvent();
        }
    }

[[ C++ - Header ]]
extern _ATL_FUNC_INFO OnClickEventInfo;
class CEventSink : public IDispEventSimpleImpl<1, CVCMapEventSink, &DIID__EventInterface>
{
    BEGIN_SINK_MAP(CEventSink )
        SINK_ENTRY_INFO(1,DIID__EventInterface, 1, OnClickEvent, &OnClickEventInfo)
    END_SINK_MAP()

    ...

public:
    void Start()
    {
        DispEventAdvise((IUnkown*) pClass);
    }
    void Stop();
    {
        DispEventUnadvise((IUnknown*) pClass);
    }

    void __stdcall OnClickEvent(int ID, bool selected);

private:
    _COMClassPtr pClass;
    CWnd* m_pTargetWnd;
}

[[ C++ - Cpp ]] 
_ATL_FUNC_INFO OnClickEventInfo= {CC_STDCALL, VT_EMPTY, 2, {VT_INT,VT_BOOL}};

void CEventSink::OnSelectedTeacher(int ID, bool selected)
{
    ...
}

/// main
void main()
{
    ...

    CEventSink  sink = new CEventSink(this);
    sink->Start();
    
    ...

    /// release
    sink->Stop();
    delete sink;    
    ...
}

이런식으로 구현하면 될것이다. 
참고 : http://msdn.microsoft.com/ko-kr/library/b91kf2t0(VS.80).aspx



ps. 여기까지 C#의 컨트롤을 가져와 C++에서 운용하는 VS2003으로 되어있는 프로젝트를 VS2008로 업그레이드 하면서 Interop에 대하여 정리하였다. 

    닷넷1.1에서 동작하던 함수들이 닷넷2.0으로 넘어오면서 발생된 문제.. 
    http://www.codeforum.net/blog/pitoosung/entry/Net-Framework-11-에서-Net-Framework-20-으로의-Migration-CollectionBase-문제#comment1328

    Custom Object를 닷넷2.0에서 직접 가져와 사용하는 부분이 닷넷2.0에서는 불가능해진것 같다.(확실하진 않음)
    Object를 가져오는 인터페이스와 Collection Enumerator를 사용하면서 가져오는 부분은 에러를 리턴한다. 
    그래서 C++은 C#의 인터페이스 함수만 참조하게 단순화 시켰다. 

    그리고 예제 코드는 클래스 이름과 인터페이스이름을 바꾸면서 적은 코드로 동작안할 가능성이 있음.. 참조만 하시길..^^;
    관련 예제 - http://msdn.microsoft.com/ko-kr/library/65t81w8a.aspx



출처 : http://icarosss.egloos.com/1999092#none
반응형
Posted by blueasa
, |