사용자 도구

사이트 도구


language:cpp:managedcpp

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

양쪽 이전 판이전 판
다음 판
이전 판
language:cpp:managedcpp [2019/11/01 16:39] kieunslanguage:cpp:managedcpp [2024/04/23 22:44] (현재) – 바깥 편집 127.0.0.1
줄 1: 줄 1:
 +
 +  
 +
 +<note important>vsts2010.net 없어짐. 이거 쓰는 시점이면 벌써 10년 전 사이트</note>
 +
 +
 +{{http://vsts2010.net|VisualStudio2010 블로그}}를 읽다가 정리한 것 뿐입니다.
 +
 +
 +====== 클래스 선언 ======
 +
 +Managed 클래스 구조체 선언은 {class, struct} 앞에 {ref, value, interface, enum} 중에 다른 것을 하나 붙여서 사용.
 +
 +Native와 같이 사용 되는 경우, 구분 짓기 위해서 그런 것 같다. ( 그렇다면 그냥 클래스를 사용하는 것도 가능? )
 +
 +<code>
 +class_access ref class name modifier : inherit_access base_type {};
 +</code>
 +
 +  * ref class, ref sturcut : 인터페이스나 ref type에서 상속 받는 경우 --> 안전빵?
 +  * value ref, value struct : 인터페이스에서만 상속 받는 경우
 +  * value 는 아래 줄을 좀 더 읽어보는게 도움이 됨
 +
 +
 +====== ^ ======
 +
 +ref 로 선언한 관리클래스는 
 +
 +  * GC에서 동적으로 생성/관리된다.
 +  * 정적은 안된다.
 +  * ^ 로 핸들을 선언해야한다. (GC 계열 언어들이 늘 그런듯이 메모리를 할당하는 것이 기본)
 +  * delete를 사용할 수 있는데, 클래스 내부 리소스 해제용이지 클래스의 메모리가 (핸들이) 삭제되는 것은 아니다.
 +  * **finalize** 를 선언해서 GC에서 소멸될 때 할일의 적는다.
 +    * 키워드 : !
 +  * 한글레퍼런스 {{http://vsts2010.net/314|http://vsts2010.net/314}}
 +
 +<code cpp>
 +ref class SampleClass 
 +{
 +public:
 +    SampleClass() {}
 +    ~SampleClass() {}
 +    !SampleClass() {}    
 +};
 +
 +//코드
 +{
 +    SampleClass^ _a = gcnew SampleClass();
 +}
 +</code>
 +
 +
 +
 +
 +
 +
 +
 +====== value 와 참조 ======
 +
 +
 +  - 한글레퍼런스 {{http://vsts2010.net/323|http://vsts2010.net/323}}
 +  - gcnew를 쓰지 않고 코드를 작성하는 경우, 컴파일러가 알아서 바꿔줍니다.
 +
 +value
 +
 +  - ref 로 선언된 관리클래스는 복사 기능이 없음
 +  - value로 선언하면 **복사가 가능한 기본 타입에 대해서 복사 작업이 가능**
 +  - gcnew 로 생성하지 않으면 스택에 생성됨 - 함수 종결시 소멸?이라는 뜻인가.
 +
 +value 특징
 +
 +  - 기본 생성자가 없다.
 +  - 복사 생성자를 가질 수 없다
 +  - 대입 연산자를 가질 수 없다.
 +  - 소멸자를 가질 수 없다.
 +  - finalize를 가질 수 없다.
 +  - 클래스간 복사를 할 수 있다.
 +  - 복사 불가능한 것을 멤버로 가질 수 없다.
 +  - 스택에 생성할 수 있다.
 +  - 인터페이스를 제외한 다른 클래스를 계승할 수 없다.
 +
 +관리클래스를 파라미터로 넘기기
 +
 +  - 파라미터에 ^ 를 붙여야 한다.<code>void func( A^ a ) {} </code>
 +
 +참조
 +
 +  - '&' 사용
 +
 +
 +
 +
 +
 +====== nullptr/interior_ptr ======
 +
 +
 +  * 레퍼 {{http://vsts2010.net/342|http://vsts2010.net/342}}
 +
 +nullptr
 +
 +  * 관리 클래스에는 0 (NULL) 대신 nullptr 을 씁니다.
 +
 +interior_ptr
 +
 +  * 네이티브 %%C++%%에서 처럼 코드의 일부의 포인터를 넘겨줄 때 씁니다.
 +
 +pin_ptr
 +
 +  * 비관리코드에서 포인터로 사용하고 싶을때 사용합니다.\\  %%C++/CLI%%에서 기존의 비관리 코드로 만들어 놓은 라이브러리를 사용할 때입니다<code>
 +ref class REFClass {
 +public: int nValue;
 +};
 +
 +void SetValue( int* pValue )
 +{
 +    *pValue = 100;
 +}
 + 
 +int main()
 +{
 +    REFClass^ refClass = gcnew REFClass;
 +    pin_ptr<int> pValue = &refClass->nValue;
 +    SetValue( pValue );
 +    pValue = nullptr;
 +}
 +</code>
 +  * 사용 후에는 nullptr로 초기화(unpin)하는게 좋다고 합니다.
 +
 +
 +====== array 클래스에 non-CLI 오브젝트 사용 ======
 +
 +array 클래스 생성 할때는 포인터 타입으로 선언해 주어야 합니다. (어찌보면 당연한??)
 +
 +<code c++>
 +class CNative { /* sample class */ };
 +// other func
 +{
 +  
 +    array< CNative* >^ _arr = gcnew array< CNative* >(2);
 +    array< CNative >^ _arr = gcnew array< CNative >(2);
 +}
 +</code>
 +
 +사용할때는 직접 메모리를 할당해줘야 합니다. 
 +
 +<code c++>
 +for(int i=0; i<arr->Length; i++)
 +{
 +    arr[i] = new CNative();
 +}
 +</code>
 +
 +또한 당연하지만, 삭제할 때도 직접 삭제해 줘야한다. GC 가 삭제해 주지 않는다.
 +
 +<code c++>
 +for( int i = 0; i < arr->Length; i ++ )
 +{
 +    delete arr[i]; 
 +}
 +</code>
 +
 +
 +====== 델리게이트에 비관리함수 할당해서 사용하기 ======
 +
 +이건 거의 팁이군요. 그래도 알면 요긴하게 쓸 수 밖에 없는 팁인 듯.
 +
 +물론 코드는, vsts2010.net 에서 가져왔습니다.
 +
 +<code c++>
 +#pragma unmanaged
 +
 +extern "C" void printf(const char*, ...);
 +
 +class A
 +{
 +// 꼭 static 을 써야 하는 건지??
 +public:  void func(char* s) { printf(s); }
 +};
 +
 +#pragma managed
 +
 +public delegate void func(char*); 
 +
 +ref class B
 +{
 +public:
 +    A* ap;
 +    B(A* ap):ap(ap) {}
 +
 +    void func(char* s) { ap->func(s); }
 +};
 +
 +int main()
 +{
 +    A* a = new A;
 +    B^ b = gcnew B(a);
 +    func^ f = gcnew func(b, &B::func);
 +    f("hello");
 +    delete a;
 +}
 +</code>
 +
 +====== 순 가상함수 ======
 +
 +**=0** 대신 **abstract** 를 사용
 +
 +순 가상함수를 추가하면 클래스도 순 가상 클래스가 될 필요가 있으므로 클래스에도 **abstract** 를 붙입니다.
 +
 +<code c++>
 +public ref class Server abstract
 +{
 +   .....
 +
 +   virtual void OnAccept() abstract;
 +};
 +</code>
 +
 +
 +
 +====== char* -> 관리코드, 관리코드 -> char* ======
 +
 +이것도 꽤 요긴할 것 같네요.
 +C++/CLI 마샬링은 {{http://msdn.microsoft.com/en-us/library/bb384865.aspx|요기 (Overview of Marshaling in C++
 +)}}에 잘 나와 있습니다.
 +
 +블로그 내용을 그대로 가져왔습니다.
 +
 +===== char* -> 관리코드 =====
 +
 +<code cpp>
 +// 비관리코드
 +int nPacketSize = 34;
 +char* pPacket = new char[34];
 +
 +// 관리코드
 +array< Byte >^ byteArray = gcnew array< Byte >(nPacketSize);
 +System::Runtime::InteropServices::Marshal::Copy( (IntPtr)pPacket, byteArray, 0, nPacketSize );
 +</code>
 +
 +===== 관리코드 -> char* =====
 +
 +<code cpp>
 +// 관리코드
 +array<Byte>^ SendData;
 +
 +// 비관리코드
 +int nLength = SendData->Length;
 +pin_ptr<Byte> pData = &SendData[0];
 +char* pBuffer = new char[ nLength ];
 +CopyMemory( pBuffer, pData, nLength );
 +</code>
 +
 +참고로 C++/CLI에서는 바이트형 배열 array<Byte>가 C#에서는 byte[] 이 됩니다.
 +
 +
 +{{tag> ManagedCpp ManagedC++}}
 +
 +
 +
 +====== legacy ======
 +  * {{http://vsts2010.net/category/C++/CLI|C++/CLI 카테고리의글}}
 +  * {{http://vsts2010.net/382|[Step. 07] 비관리 클래스에서 관리 클래스를 멤버로, 관리 클래스에서 비관리 클래스를 멤버로}}
 +  * {{http://vsts2010.net/378|프로퍼티(property)}}
 +  * {{http://vsts2010.net/380|델리게이트(delegate)}}
 +  * {{http://vsts2010.net/381|이벤트(event)}}
 +  * {{http://vsts2010.net/379|enum}}
 +  * {{http://vsts2010.net/485|[Step. 16] array 클래스에 non-CLI 오브젝트 사용}}
 +  * {{http://vsts2010.net/495|[Step. 17] 델리게이트에 비관리 함수를 할당하기 그리고 다음 예고}}
 +  * {{http://vsts2010.net/503|[Step. 19] char* -> 관리코드, 관리코드 -> char*}}