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_MyLib, CLSID_MyCoClass, IID_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
반응형
'Programming > C#' 카테고리의 다른 글
TreeNode Visual C# 도구 설명을 추가하는 방법 (0) | 2011.11.21 |
---|---|
TreeView에서 Find 함수 사용 방법 (0) | 2011.11.20 |
C#에서 포인터 (0) | 2011.11.15 |
TreeView 이용하기(추가/선택삭제/체크삭제) (0) | 2011.11.14 |
TreeView에서 Node 검색 및 카테고리 구현 (0) | 2011.11.14 |