'etc/xna'에 해당되는 글 4건

  1. 2010.08.10 C#으로 네이티브 코드 접근하기 part 3. 네이티브클래스 랩퍼
  2. 2010.08.03 C#으로 네이티브 코드 접근하기 part 2
  3. 2010.07.31 C#으로 네이티브 코드 접근하기 part 1
  4. 2010.07.25 C#으로 일리히트 엔진 다루기

C#으로 네이티브 코드 접근하기 part 3. 네이티브클래스 랩퍼

|
이전 강좌에서 만들었던 CTest클래스를 그대로 사용하겠습니다.

매나지드c++로 랩퍼 DLL을 만들어서 이것을 우회적으로 경유하여 네이티브코드와 매나지드코드를 붙이는 방법입니다.

먼저 프로잭트 세팅을 다음과 같이 해줍니다.



기본적으로 매나지드 코드이기 때문에 네이티브 c++쪽 선언정보를 다음과 같이 #pragma unmanaged 키워드로 감싸서 표기 합니다.



이렇게 하면 매나지드 c++코드에서 네이티브 코드를 혼용해서 사용할수 있습니다. 단점은 CLR에서는 인탤리젼트 기능이 무력화되있기때문에 약간은 좀 불편 하실수도있습니다. 그러나 비주얼 어시스트를 쓰면 됩니다. ^^;

다음은 랩퍼 클래스입니다.



CreateTest라는 함수를 먼저 보면 인스턴스를 만들어 주는 함수인데요.




네이티브 코드의 정적 함수를 호출하여 네이티브 객체를 Wrap함수에 넘겨주는 일을 합니다.

그 다음 Wrap에서는 받아온 네이티브 포인터를 매나지드 참조형( ^  이라고 표기되는... )으로 바꿔 주는 역활을 합니다.


gcnew를 써서 랩퍼 객체를 만들어 줍니다. 생성자는 인자로 네이티브포인터를 받습니다.

생성자는 아래와 같이 구현됩니다.



가장 중요한(?) 더하기 기능을해주는 함수는 아래와 같이 네이티브 코드를 원격 호출하는것으로 구현됩니다.





이렇게 만들어진 DLL은 매나지드코드와 연결이 가능한 DLL입니다. 이걸가지고 각종 .Net40 환경의 여러 언어들과 소통이 가능합니다.

C#프로잭트에 Add Reference 해주셔야합니다.
lime.dll은 매나지드 랩퍼 dll이고
testDll.dll은 순수 네이티브 dll 입니다.



C#으로 쓰는 예는 다음과 같습니다.





소스 첨부 합니다.




And

C#으로 네이티브 코드 접근하기 part 2

|
이번에는 저번 강좌에 이어서 클래스를 다뤄 보도록 하겠습니다.

약간 강좌가  외전으로 빠지는데요. ^^;

우선 명시적인 방법으로....

네이티브 코드에서 네이티브코드DLL로 작성된 클래스를 얻는 전통적인 방법부터 알아 보도록 하겠습니다.

class __declspec(dllexport) CTest {
public:
int Add(int a,int b);

static CTest *Create();
static void Delete(CTest* pobj);
};

int CTest::Add(int a,int b)
{
return a+b;
}

CTest* CTest::Create()
{
return new CTest();
}

void CTest::Delete(CTest* pobj)
{
delete pobj;
}

이와 같이 클래스를 선언해줍니다.  외부에서 동적으로 클래스를 참조하기 위해서는 ' __declspec(dllexport) ' 가 꼭 필요합니다.


사용하는 쪽에서는 다음과 같이 클래스를 정의만 해줍니다.



암시적접근은 정적 라이브러리 쓰는것과 동일하지만 명시적으로 접근 할때는 다음과 같이 펙토리 함수등을 통해서 객체를 직접 얻어와야 합니다.



정적 함수인 Create의 함수 포인터를 이용해서 객체에 대한 인스턴스를 직접 얻어옵니다. 이것을 this포인터로 사용합니다.
외부 참조 가능한 클래스멥버함수의 호출규약은 첫번째인자에 this포인터를 넘겨주도록 정해져있습니다. 

CTest::Add 함수의 포인터를 얻어와 첫번째 인자로 방금 얻은 객체 포인터를 넘겨줍니다.

pCalAdd(pCalc,10,7);

pCalc는 Create함수를 통해 얻어진 CTest클래스의 인스턴스포인터 입니다.
pCalAdd는 CTest::Add의 함수 포인터 입니다.

여기서  GetProcAddress 로 넘겨주는 함수이름이 [?Create@CTest@@SAPAV1@XZ] 처럼 이상한데요. 이유는 C++컴파일러가 외부 참조가능하도록 전통적인 c언어형식으로 함수를 다시 만들기 때문입니다.

원래는 2강좌로 마칠려고 했는데 쓰다보니 약간 두서 없이 방향이..... ㅡ.ㅡ;;;

다음번엔 매나지드 코드와 네이티브 클래스 연결법에 대해서 알아보도록 하겠습니다.









And

C#으로 네이티브 코드 접근하기 part 1

|
닷넷 4.0 환경에서 네이티브 코드 와 매나지드 코드를 연결하는 방법을 2 회정도로 나누어서 다뤄볼까합니다.

닷넷에 대한 기초적인 개념이 구조는 다른 좋은 강좌들이 많으니 넘어가기로 하겠습니다. 저는 실제로 응용사례를 통해서 방법을 소개 해볼까합니다.

기본 아이디어는 다음과 같습니다.




그림에서 처럼 네이티브로 작성된 DLL 네이티브 코드와 혼합된 DLL을 경유해서 닷넷 기반언어에서 사용하는 방법입니다.
게임개발시 이런 방법을 사용할경유 장점은 네이티브코드로된 게임엔진으로 툴제작시 mfc를 사용하지않고 좀더 다루기 쉬운 C#을 사용해서 툴을 만들수있다는 장점있습니다.
뿐만 아니라 게임에서 많이 쓰이는 루아나 파이썬대신 C#으로 스크립트언어로도 사용할수있다는 점이있습니다. C#을 스크립트언어로 사용할경우 VS강력한 IDE의 화력지원을 받아 좀더 효과적인 개발을 할수있기때문입니다.

먼저 간단하게 전역함수를 콜해보는 예제를 살펴 보도록 하겠습니다.



이런식으로 네이티브 DLL을 만든 다음 이것을 매나지드 코드 DLL로 한번더 랩핑을 해주어야합니다.


class 이름 앞에 ref라고 붙는데 이렇게 하면 닷넷 기반의 다른 언어들이 같이 쓸수잇는 클래스가 만들어 집니다. ref가 붙지 않으면 오직 네이티브에서 만 쓸 수 있는 클래스가 만들어 지고요.

 

C#쪽에서는 다음과 같이 사용을 할 수 있습니다.

다음에는 네이티브 코드쪽 class를 매나지드 코드 class로 랩핑하여 매나지드 언어에서 콜하는 방법을 알아보도록 하겠습니다.

















And

C#으로 일리히트 엔진 다루기

|
많은 게임관련 교육기관에서 닷넷환경에서는 XNA를 사용하려고 합니다만 배우기쉽고 퍼포먼스가 좋을지는 몰라도
XNA는 기능 확장성 관련해서 너무 취약합니다.(확장이 불가능하다 정도로 표현하는게 맞을 수도있습니다.)
예를들어 픽셀단위로 접근을 하려해도 쉽지않습니다.
픽셀쉐이더를 쓰면 되지않나요? 이렇게 반문 하실수도있지만 그 정도 아시는 분이 XNA를 왜? 배우려 하겠습니다^^; 그리고 어린학생이 픽셀쉐이더를 제데로 쓰는 학생이 몇이나될까요?

저는 교육현장에서 6년정도 일을 하고있습니다만 의외로 학생들의 요수사항은 쉽지않습니다.
왜냐하면 어린학생들은 어른들이 생각하지도 못한 정말 기발한 발상을 합니다. 그렇기 때문에 빠르게 개발할수 있다는 장점만을 내세운 XNA는 전혀 도움이 되지 않습니다. 차라리 스타2에디터를 가르치는게 더나을수도 있습니다.
게임은 창의적이여야 합니다. 그러나 범용성과 대중성을 내세워 게임제작에서 반드시 필요한 창의성을 제데로 표현하지 못하게 한다면 그것은 잘못된 정책 이라고 생각합니다.

한마디로 XNA를 정리하자면 '코드배이스이나 툴배이스보다 유연성이 더떨어진다.' 는 결론입니다. 누가 이런걸써야 하나요^^? 정말 생각 해보면 개그스러운 발상입니다.

그래서 닷넷기반위에서 게임프로그래밍을 하기 위해서 기존네이티브코드로된 엔진을 매나지드방식으로 불러오는 방법을 생각해볼수있습니다. 
저는 오거,일리히트,네뷸러,판다3D등의 공개엔진중에서 일리히트엔진을 선택했는데요.
몇가지이유가있습니다.
첫째로 유연성을 뽑을수있습니다. 유연성에있어서는 오거도 멀티 플랫폼이지않느냐 반문하실수도있겠는데요. 제가 말하는건 멀티 플랫폼뿐만아닙니다. 언어적으로도 유연해야된다고봅니다. 예를들면 성경책을보면 주님의 말씀은 여러개의 언어로 표현되지만 의미는 하나를 가지고있습니다. 이처럼 일리히트는 객체지향이라는 복음으로  설계가 되었습니다. 문제는 그순수성에 있습니다. 타엔진은 효율성을 내세워 c++종속적인 면을 일부가지게됩니다만 일리히트는 객체지향이라는 유일신하나만으로 순수하게 설계된 철학을 가지고있습니다. 결론적으로 일리히트는 언어에도 무관한구조를 가지게되었습니다. 일리히트를 표현 하는데 언어는 중요치 않습니다. c++로 구현된 예가 있을뿐 c++기반은 아니기 때문입니다.(영어로 쓰여진 성서책이있을뿐 성서가 영어는 아니죠.)

이런 철학은 닷넷과 궁합이 잘맞아떨어집니다.


일리히트엔진 공식 프로잭트 싸이트는 http://irrlicht.sourceforge.net 입니다. 여기서 정식 버전(1.7.1)을 릴리즈하고있으며 현제는 1.8버전을 준비중에 있습니다. 여러 언어와 바인딩한 예가있는데요. 그중에서 닷넷기반 으로 바인딩하는 방법에 대해서는 일리히트 포럼에 가셔셔 먼저 irrlicht lime을 검색하시면 관련 정보를 얻으실수있습니다.

소스포지 프로잭트가 위와같이 진행되고있으며 현재(2010.7) 버전 0.5가 나온상태입니다.

접근방식은 네이티브코드쪽 irrlicht.dll을 중간단계의 매나지드코드dll인 irrlichtlime.dll을 사용해서 닷넷기반의 매나지드코드로 접근 하는 방식을 사용했습니다.
이 방법의 최대장점은 이해하기 쉽고 단순하다는것입니다. 또한 그다지 큰단점도 없는듯합니다.




위의 소스 코드는 네이티브 일리히트코드중에 createDevice함수를 랩핑한 예를 보여줍니다. 


매나지드코드용 랩퍼 dll프로잭트를 만들때는 위와같이 CLR을 사용한다는 옵션을 줍니다.




라임솔루션 디랙토리 모양입니다. irrlichtLime프로 잭트가 랩퍼 입니다. 결과물은 irrlichtLime.dll이 나옵니다.

연습으로 간단하게 화면에 큐브를 돌려보는 예제를 만들어 보겠습니다.
먼저 프로잭트를 추가합니다.


콘솔 어플로 만듭니다.





라임을 컴파일하면 매나지드 랩퍼(irrlichtLime.dll)가 /bin 디랙토리상에 존재하므로 실행파일이 같은 곳에 있도록 지정해줍니다.

리퍼런스를 추가 합니다.


브라우져 탭으로 가셔셔 /bin 디랙토리에 있는 irrlichtLime.dll을 선택합니다.



그리고 소스를 다음과 같이 편집해 줍니다.(program.cs)

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            IrrlichtLime.IrrlichtDevice device = IrrlichtLime.IrrlichtDevice.CreateDevice(IrrlichtLime.Video.DriverType.Direct3D9, new IrrlichtLime.Core.Dimension2Di(640, 480));

            IrrlichtLime.Video.VideoDriver driver = device.VideoDriver;
            IrrlichtLime.Scene.SceneManager smgr = device.SceneManager;

            IrrlichtLime.Scene.SceneNode node = smgr.AddCubeSceneNode();

            node.SetMaterialFlag(IrrlichtLime.Video.MaterialFlag.Wireframe, true);
            node.SetMaterialFlag(IrrlichtLime.Video.MaterialFlag.Lighting, false);

            IrrlichtLime.Scene.SceneNodeAnimator anim = smgr.CreateRotationAnimator(new IrrlichtLime.Core.Vector3Df(0, (float)3.14/4, 0));
            node.AddAnimator(anim);
            anim.Drop();

            smgr.AddCameraSceneNode(null, new IrrlichtLime.Core.Vector3Df(0, 10, -50), new IrrlichtLime.Core.Vector3Df(0, 0, 0));

            while (device.Run())
            {
                driver.BeginScene(true, true, new IrrlichtLime.Video.Color(100, 101, 140));

                smgr.DrawAll();

                driver.EndScene();
            }

            device.Drop();
        }
    }
}

실행 결과입니다.











And
prev | 1 | next