Post List

2015년 1월 6일 화요일

[Reny Kim] DLL 제작방법 – 5.DLL for .NET

5.1 Basis

Visual C++은 Windows SDK, MFC와 .Net Framework를 동시에 사용하여 개발가능한 능력을 갖고 있다. C++/CLI(이전 Managed Extensions for C++) 불리우는 .Net Framework를 위한 언어규격을 사용하여 .NET Framework를 위한 코드를 개발할 수 있다.
이를 이용하여 .Net과 C API의 중간자로서, .Net에서 직접적으로 사용하기 힘든 각종 C Library를 .Net에서 직접사용할 수 있도록 하는 DLL을 만들 수 있다. 즉, 내부적으로는 C API/MFC를 사용하고 외부로의 기능노출을 .Net으로 개발하여 중간자 역할을 하는 DLL을 개발가능하다.

5.1.1 Features
  • 내부적으로 C API, MFC 등 Visual C++의 모든 기능을 사용할 수 있다.
  • C++/CLI를 사용하여 .Net의 모든 Class를 사용할 수 있다.
  • C++/CLI를 사용하여 .Net에서 참조만으로 사용가능한 Class를 만들 수 있다.

5.1.2 API Proxy Class
.Net에서 MFC 기능을 사용하고 싶다거나, 복잡한 Pointer 구조 등을 사용하는 C API를 .Net에서 사용하고 싶은 경우, 기존의 Visual C#이나 Visual Basic에서는 사용이 불가하거나, 그 사용법의 복잡함으로 인하여 개발이 용이하지 않은 경우가 많다.
이러한 경우, Visual C++을 이용하여 C Library를 .Net과 호환시켜주는 Proxy Class를 만들어, .Net에서 사용할 수 있도록 할 수 있다.


이렇게 하는 경우 .Net에서 사용할 수 없는 C++ Class를 사용할 수 있게 하여 C++ 개발자와 C# 개발자의 협력이 가능하다.

5.1.3 C++/CLI 구문
  • Class 선언
C++/CLI에서 관리되는 형식의 선언방법은 아래와 같다.
ref class Block {};                // reference class
value class Vector {};             // value class
interface class I {};        // interface class
ref class Shape abstract {};       // abstract class
ref class Shape2D sealed: Shape{}; // derived class
  • 개체 선언
C++/CLI에서 관리되는 형식의 개체선언은 아래와 같이 “^”를 이용하여 선언한다. “^”는 관리되는 개체형식의 Pointer를 의미한다.
public ref class Form1 : System::Windows::Forms::Form {
   System::ComponentModel::Container^ components;
   System::Windows::Forms::Button^ button1;
   System::Windows::Forms::DataGrid^ myDataGrid;
   System::Data::DataSet^ myDataSet;
};
  • 관리되는 Object 생성
C++/CLI에서 Object의 생성은 “gcnew”를 사용한다.
Button^ button1 = gcnew Button;        // managed heap
int * pi1 = new int;                   // native heap
Int32^ pi2 = gcnew Int32;              // managed heap
  • CLR 배열
“array” keyword 사용
array<Object^>^ myArr
array<int,3>^ myArr
  • Property (속성)
“property” keyword 사용
public ref class Vector sealed { 
   double _x;

public:
   property double x 
   {
      double get()             { return _x; }
      void   set( double newx ){ _x = newx; }
   } 
};

5.2 Making C++/CLI DLL

5.2.1 Object
간단한 DLL을 만들기 위하여 아래와 같은 기능을 가지는 Class를 DLL로 만들기로 한다.

  • MFC의 CFtpConnection Class를 .NET에서 사용할 수 있는 CLR Class를 제작
  • 동작의 시험을 위하여 Connect/Disconnect 기능만을 구현한다.

5.2.2 Implementation
  • 아래와 같이 새 프로젝트를 선택하고 “Visual C++” 카테고리의 “클래스 라이브러리”를 선택하여 프로젝트를 생성한다.

  • 프로젝트 속성 페이지에서 “구성속성 ? 일반” 카테고리를 선택하여 “MFC사용” 항목에서 “공유 DLL에서 MFC사용”을 선택한다.
  • MFC를 사용하기 위하여 Stdafx.h에 아래와 같이 MFC Header 파일을 포함시킨다.
[Stdafx.h]
#include <afxwin.h> 
#include <afxinet.h>
  • .Net에서 사용할 CLR Class를 작성한다. 실제 내부적으로 사용할 MFC의 CFTPConnection Class를 위한 변수를 멤버로 추가한다. Class는 Resource 반환을 위하여 IDisposable Interface를 구현한다. 또한 서버의 접속/접속해제를 위한 함수를 추가한다. 함수의 파라미터는 .NET에서 사용할 것이므로 CLR Type을 사용한다.
[FTPProxySample.h]
namespace FTPProxySample {

   public ref class FtpConnection : public IDisposable
   {
   public:
                 FtpConnection();
                 ~FtpConnection();

                 void Open(String^ serverURL, int Port, String^ ClientName, String^ UserID, String^ Pwd);
                 void Close();

   private:
                 CInternetSession* m_pSession;
                 CFtpConnection*  m_pFtpConn;
   };

}
  • 실제 Connect와 Close의 구현을 추가한다. 각 함수는 실제 MFC Class의 오브젝트를 이용하여 처리를 하면된다. 이렇게 하는 경우, .NET에서 함수를 호출하면, 함수에서 MFC를 접근하여 각 처리를 수행하게 된다.
[FTPProxySample.cpp]
namespace FTPProxySample
{
   FtpConnection::FtpConnection()
   {
                 m_pSession = NULL;
                 m_pFtpConn = NULL;
   }

   FtpConnection::~FtpConnection()
   {
                 Close();
                 System::GC::SuppressFinalize(this);
   }

   void FtpConnection::Open(String^ ServerURL, int Port, String^ ClientName, String^ UserID, String^ Pwd)
   {
                 CString serverURL(ServerURL);
                 CString userID(UserID);
                 CString password(Pwd);
                 CString clientName(ClientName);

                 m_pSession = new CInternetSession(clientName);

                 // FTP 접속
                 try
                 {
                              m_pFtpConn = m_pSession->GetFtpConnection(serverURL, userID, password, Port);
                 }
                 catch(CInternetException* pe)
                 {
                              // Exception 처리
                 }
   }

   void FtpConnection::Close()
   {
                 if(m_pSession != NULL)
                 {
                              m_pSession->Close();
                              delete m_pSession;
                              m_pSession = NULL;
                              m_pFtpConn = NULL;
                 }
   }
}
  • 컴파일을 하면, .NET에서 참조가능한 FTPProxySample.dll이 만들어진다.
5.3 Using C++/CLI DLL
  • 만들어진 DLL은 .NET용 DLL이므로, .NET 프로젝트에서 “참조추가”를 하면, 바로 DLL내의 Class를 사용할 수 있다.
  • 아래와 같이 참조한 DLL의 Class의 객체를 생성하여 사용한다.
private void button1_Click(object sender, EventArgs e)
{
    using (var ftp = new FTPProxySample.FtpConnection())
    {
        try
        {
            ftp.Open("server-url", 21, "Test", "id", "password");
            MessageBox.Show("Success");
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }            
    }
}

출처 : http://rainiac.com/dev/

댓글 없음:

댓글 쓰기