조회 수 21750 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

+ - Up Down Comment Print
?

단축키

Prev이전 문서

Next다음 문서

+ - Up Down Comment Print

출처 : http://blog.naver.com/limdp99/60034273093



이번에 파티클 에디터를 만들면서 mfc 말고 c# 을 사용해보았는데 c# 문법에 대한 자료는 많지만,

c++ lib 를 c# 에서 사용하는 방법에 대해 자세히 나온곳이 없어서 간단하게 정리해보았습니다.

 

작업순서는

1) c++ 로 lib 작성 (lib)

2) c++/cli 로 wrapper 를 만들고 (dll)

3) c# 에서 wrapper dll 를 호출해서 작업을 하게됩니다.

 

 

직접 해보자면

1) c++ 로 lib 를 하나 만듭니다. 저는 간단하게 다음과 같은 class 를 만들었습니다.

 

class cppLib

{

public :

        int     addValueint value1int value2 )

        {

               return ( value1 + value2 );

        }

};
 
 
2) 그 다음에는 c++/cli 로 프로젝트를 만듭니다.

 

cli-limdp99.jpg?type=w2

 
 
이곳에서 아까 만든 lib 를 link 시켜서 wrapper class 를 만듭니다.
 
[ header ]

namespace cliWrap

{

        public ref class cppLibWrap

        {

        protected :

               cppLib *       m_pCppLib;

 

        public :

               cppLibWrap();

               virtual ~cppLibWrap();

 

               int     addValue( int value1, int value2 );

        };

 

// namespace - cliWrap

 

 

[ source ]

namespace cliWrap

{

        cppLibWrap::cppLibWrap() : m_pCppLib( new cppLib )

        {}

 

        cppLibWrap::~cppLibWrap()

        {

               if( m_pCppLib )

               {

                       delete m_pCppLib;

                       m_pCppLib = 0;

               }

        }

 

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

        int     cppLibWrap::addValue( int value1, int value2 )

        {

               return m_pCppLib->addValue( value1, value2 );

        }

 

// namespace - cliWrap

 

 

3) wrapper class 작성이 끝났으면  c# 으로 프로젝트를 만듭니다.


cs-limdp99.jpg?type=w2

 

c# 프로젝트 생성후에 위에서 작업한 2개의 프로젝트를 추가시켜줍니다.

 

wrapper class 쪽에서 만들어지는 dll 을 c# 에서 사용하게 되는데 매번 변경사항이

있을때마다 복사하기가 번거롭기 때문에 빌드시마다 자동으로 복사해주는 작업을 해줍시다.

 

cs2-limdp99.jpg?type=w2

 

Command Line 에 copy "$(TargetPath)" "$(SolutionDir)\simpleProject\$(TargetFileName)" 를

자신의 프로젝트 폴더에 맞게 적당히 수정해서 적어줍니다.

 

cs3-limdp99.jpg?type=w2

 

그 후에 dll 복사를 위해 wrapper 프로젝트를 다시 빌드해줍니다.

이제 c# 프로젝트에 c++/cli 로 만든 dll 을 붙여줍니다.
 

cs5-limdp99.jpg?type=w2

 

아까 만든 wrapper class dll 을 추가시켜줍니다.

 

cs6-limdp99.jpg?type=w2


 

 

이제 작업이 끝났습니다.

c# 프로젝트에서는 다음과 같이 그냥 사용하시면 됩니다.

 

namespace simpleProject

{

    public partial class Form1 : Form

    {

        private cliWrap.cppLibWrap m_cppLibWrap = null;

 

        public Form1()

        {

            InitializeComponent();

 

            m_cppLibWrap = new cliWrap.cppLibWrap();

 

            int returnValue = m_cppLibWrap.addValue(12);

 

            MessageBox.Show(returnValue.ToString());

        }

    }

}
 

 
이제 Property Grid 를 비롯해 c# 의 막강한 기능을 누리시면 됩니다.
 
다음에는 c# 에서 Property Grid 를 붙힐때 c++ lib 작업시에 미리 등록을 해서
자동화하는 방법에 대해 설명하고자 하는데 언제가 될지는 모르겠습니다. 하하~
 
 
ps. c#, c++/cli 문법에 대한것은 인터넷에 많기때문에 이곳에서 다루지 않았습니다.
참고할만한 c# 서적이 pdf 로 공개되어있습니다. 참고하시길 바랍니다.





출처 : http://six605.tistory.com/384



■ C++/CLI 예제의 전체적인 흐름



C/C++ 코드를 C# 에서 사용하는 가장 기본적인 방법은 Wrapper 클래스를 통한 방법이다. 
C++ 코드를 컴파일 하여 Static Library 파일로 만든다. 만들어진 lib 파일을 C++/CLI 을 이용하여
감싸서 dll 파일로 만든다. 이로써 C++ 로 작성된 Native Code 를 C# 에서 이용 가능한 Managed Code 로 만든 것이다.
C# 에서는 C++/CLI 로 만들어진 dll 파일을 참조하여 사용하기만 하면 된다.




■ C++ 로 작성된 Native Code

간단하게 두개의 정수값을 인자로 받아 두 값의 합을 리턴하는 함수를 작성한다.
추후에 C++/CLI 로 감싸기 쉽게 하기 위하여 클래스로 작성한다.



Visual C++ 프로젝트 형식 → Win32 → Win32 콘솔 응용프로그램 선택




사용하려는 Native Code 를 Static Library 로 만들어야 하기 때문에 응용프로그램 설정에 "정적 라이브러리" 체크 해준다.
"미리 컴파일된 헤더" 에도 체크를 해주자(Default 설정)


솔루션 탐색기를 보면 stdafx.cpp, stdafx.h, targetver.h 3개의 파일이 만들어진다.


두개의 정수값을 인자로 받아 합을 리턴하는 함수를 클래스로 작성해 보았다.

class AddCal
{
private:    
    explicit AddCal(const AddCal &_rAddCal);    
    AddCal &operator=(const AddCal &_rAddCal);

public:
    explicit AddCal();
    virtual ~AddCal();

    int Add(int _num1, int _num2);
};

< AddCal.h >


#include "stdafx.h"
#include "AddCal.h"


AddCal::AddCal(void)
{
    // nothing
}


AddCal::~AddCal()
{
    // nothing
}


int AddCal::Add(int _num1, int _num2)
{
    return (_num1 + _num2);
}

< AddCal.cpp >


 위 코드를 컴파일 하면 "UnmanagedCal.lib" 라이브러리 파일이 생성 된다.




■ C++/CLI 를 이용하여 Native Code 감싸기

Native Code 를 Managed Assembly (.dll) 파일로 만들어야 한다.
이때 사용하는 것이 C++/CLI 로서 클래스를 작성하여 Native Code 를 감싼다.

솔루션에 새로운 프로젝트를 생성한다. 프로젝트 이름은 managedCal 이라고 정했다.



Visual C++ → CLR → 클래스 라이브러리 선택
(C++/CLI 는 Visual Studio 2005 이상부터 지원한다. 위에서와 같이 툴 자체에서 템블릿을 제공)




생성된 managedCal 프로젝트에 Native Code 로 작성했던 "AddCal.h" 헤더 파일을 추가한다.




솔루션 탐색기에서 마우스 오른족 버튼을 누르고 팝업 메뉴에서 "참조" 를 선택한다.
앞서 작성한 UnmanagedCal 프로젝트를 참조로 추가한다.


C++/CLI 를 이용하여 Native Code 를 클래스를 작성하여 감싸준다.

// managedCal.h
#pragma once
#include "..\UnmanagedCal\AddCal.h"
using namespace System;

namespace managedCal
{
    public ref class AddCalWrap
	{
    protected:
        AddCal *m_pAddCal;

    public:
        AddCalWrap();
        virtual ~AddCalWrap();

        int Add(int _num1, int _num2);
	};
}

< managedCal.h >

앞서 프로젝트에 추가한 AddCal.h 헤더파일을 include 해준다.
ref class 키워드 처럼 C++/CLI 문법을 이용하여 작성해야 한다.
여기서는 Native Code 의 AddCal 클래스 인스턴스를 참조하는 포인터 변수와 
AddCal 클래스의 Add() 함수를 호출할 멤버 함수를 정의 하였다.


// 기본 DLL 파일입니다.

#include "stdafx.h"
#include "managedCal.h"

namespace managedCal
{
    AddCalWrap::AddCalWrap()
        : m_pAddCal(new AddCal)
    {

    }

    AddCalWrap::~AddCalWrap()
    {
        if (m_pAddCal)
        {
            delete m_pAddCal;
            m_pAddCal = 0;
        }
    }

    int AddCalWrap::Add(int _num1, int _num2)
    {
        return (m_pAddCal->Add(_num1, _num2));
    }
}

< managedCal.cpp>

기본 생성자에서 Native Code 의 AddCal 클래스를 동적으로 생성한다.
소멸자 에서는 생성자에서 생성한 AddCal 클래스 인스턴스를 메모리 해제 한다.
Add() 함수는 AddCal 클래스의 Add() 함수를 호출한다.


컴파일 하면 "managedCal.dll" 파일이 만들어 진다.




■ C# 을 이용하여 C++/CLI 로 생성된 dll 파일 이용하기

이제 Managed Code 인 C# 을 이용하여 C++/CLI 로 작성된 클래스 라이브러리 파일을 사용하면 된다.

테스트할 C# 프로젝트는 간단하게 콘솔 어플리케이션으로 작성 했다.



프로젝트 이름은 CliDemo 이다.




솔루션 탐색기에서 CliDemo 프로젝트에 위에서 작성한 "managedCal" 프로젝트를 참조 추가 시킨다.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CliDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            managedCal.AddCalWrap obj = new managedCal.AddCalWrap();

            Console.WriteLine(obj.Add(1, 2));
            Console.Read();
        }
    }
}

< Program.cs >  

managedCal 프로젝트를 참조 추가 시켰으므로 managedCal 클래스를 참조할 수 있다. 인텔리센스에서 managedCal 네임스페이스가 보이지 않은다면 무엇인가 문제가 있는 것이다.
C++ Native Code 를 감싸고 있는 AddCalWrap 클래스를 동적으로 생성 시킨다. 사용하는 코드는 C# 프로그래밍을 하는 것처럼 사용한다. 생성된 인스턴스에서 Add 메소드를 호출 시키면 결과 값이 리턴된다.










개체 브라우저를 이용하여 C++/CLI 로 작성한 AddCalWrap 클래스를 보았다.
Managed Code 이기에 최상의 클래스는 Object 클래스 이며, IDisposable 인터페이스를 상속 받으므로
가비지 컬렉터가 자동적으로 메모리 해제 시켜 준다. 단, AddCalWrap 클래스에서 동적으로 생성한 AddCal 클래스는
가비지 컬렉터의 소관이 아니므로 ~AddCalWrap() 소멸자에서 명식적으로 메모리 해제 시켜줘야 한다.

 참고로 C++/CLI 를 이용한 프로젝트를 참조추가 하지 않고, 해당 dll 을 참조해도 똑같이 사용할 수 있다.
지금은 int 와 같은 간단한 정수형을 마샬링 했기 때문에 쉽게 되었지만 전달되는 인수가 복잡해지면 쉽지 않을 것 같다.
필요할 때 하나씩 알아봐야 겠다.



나눔글꼴 설치 안내


이 PC에는 나눔글꼴이 설치되어 있지 않습니다.

이 사이트를 나눔글꼴로 보기 위해서는
나눔글꼴을 설치해야 합니다.

설치 취소

Designed by sketchbooks.co.kr / sketchbook5 board skin

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5