회사에서 코어로 되어있는 C++엔진을 C#으로 올리는 작업을 하게 되었습니다.

속도와 최적화를 위해 C++로 만든 라이브러리 같을 것을 생산성을 높이기 위해 C#에서 사용할 수 있습니다 

그 방법은 크게 두가지가 있는데 

첫번쨰는 C++/CLI를 이용해서 넘겨주는 것이고

두 번쨰는 DLLImport 해주는 방법입니다 저희 회사는 모종?의 이유로 첫번째를 사용합니다 

저도 처음 해보는 것 이기에 해보다 오늘 성공! 하고 잊지 않기 위해 포스팅! 첫번째 방법도 라이브러리가 정적,동적 두개가 있기때문에 크게 두가지로 나눌수 있는데

1.C++로만든 Lib ->C++/CLI -> C#

2.C++로만든 Dll -> C++/CLI -> C# 

회사 엔진은 Dll로 배포하기에 일단 2.으로 포스팅을 먼저 하겠습니다.

1.먼저 Dll이 필요합니다. 만약 없다면 하나 만들어봅시다 https://msdn.microsoft.com/ko-kr/library/ms235636.aspx

2.저 예제를 그대로 빌드하고 컴파일 하면

MathFuncsDll.dll

MathFuncsDll.lib

라고 나오는데 이름은 사실 상관없습니다. dll과 Lib 파일만 있으면 됩니다. 아 header 파일도 필요합니다.

3.자 이제 정말 만들어봅시다! 비주얼 스튜디오를 시작하고 파일->새로만들기->프로젝트를 누르고

Visual C++ -> CLR -> 클래스라이브러리를 선택합시다 솔루션 이름과 프로젝트 네임은 전 스샷처럼 했지만 자유롭게 정해봅시다

그러고 확인을 누르면 이렇게 되고 ref class가 자동으로 생성됩니다. 아마 Class1 이라고 나올것 입니다 

저는 파일이름과 맞추어주기위해 이름을 dllClr로 바꾸어 생성했습니다. 

이제 프로젝트의 솔루션이 있는 경로로 가서 dll,lib,h 파일을 '일단' 이 프로젝트 폴더에 넣어줍니다

사실...설정이 더 빡세고 짜증난다 ㅠㅠ 이제 설정을 해봅시다.

먼저 어떤 함수가 무엇을 하는지 알아야 합니다 그걸 알기위해서 헤더파일도 같이 있습니다.

그래서 프로젝트에 헤더파일란에 저 헤더파일을 추가해줍시다. 방금 일단 저 폴더에 넣자고 했는데 지금이야 작은 Dll이지만 나중에 커지면 관리하기 힘드니 지금 폴더를 나누어 줍시다 그래서 저는 include 폴더를 만들어서 헤더파일을 넣어주고 lib 폴더를 만들어서 dll과 lib 파일을 넣어주었습니다

자 아까 나누어주었던 라이브러리를 프로젝트에 추가해 줍시다.

하게 되면 왼쪽 소스 처럼 #include 에서 경로를 입력해주지 않아도 됩니다 

이제 아까 추가해준 헤더파일을 보면서 어떤 함수가 있는지 보면서 C++/CLR로 적어줍니다

소스파일 입니다 dll에 있는 함수를 가져옵니다

라이브러리도 추가해 주어야 하는데요 링커->입력 추가 종속성에서 라이브러리를 등록해줍니다! 주의 하실것은 라이브러리가 있는 폴더가 아니라

xxxx.lib를 직접 등록해 주어야 합니다.

한번 빌드! 네 잘 됩니다!

자 이제 C# 프로젝트를 만들어서  dll에 있는 것들을 가져와서 사용해 봅시다!

 

CLR 도 추가해줍니다. 이렇게 dll을 한번 감싼 것을 C# 프로젝트에서 사용할수 있게 합니다.

프로젝트 오른쪽 클릭 추가 참조를 눌러줍니다

참조관리자에서 솔루션에서 CLR프로젝트를 추가해서 넣어줍니다

CLR은 빌드 만 해주기때문에 그 라이브러리를 사용해서 직접 보여주는 것은 C# 프로젝트가 합니다

때문에 C# 프로젝트를 시작 프로그램으로 설정해 줍니다

여기서 가장 중요한것! 그 맨처음의 dll을 실행 파일이 있는 곳에 넣어주어야 합니다.

CLR이 참조하는 것들을 가져와야 하기떄문에 실행시점에 dll 파일이 있어야 합니다.(이것때문에 2시간 삽질 ㅠㅠ)

obj으로 가져온 dll속에 있는 함수들! 사용해 보면 잘 나옵니다!


ps.혹 실행이 안되신다면 64비트 32비트 맞추기 위해 빌드 에서 32비트 기본 사용을 체크 해제해 주세요

 

 

 

먼저 제가 첨부해 놓은 파일을 받아봅시다!

파일 이름에서 유추할수 있듯이 가위 바위 보 입니다.

윈도우즈 10 앱으로 제가 만들 가위 바위 보는 제가 그림을 클릭 하면 가위 바위 보를 내게 되고 컴퓨터도 그렇게 내어서 이겼는지 졌는지를 알수 있는 앱입니다.

저번에 그냥 텍스트 블록과 버튼만 필요했던 것과는 달리 이번에는 알아야 할것이 몇가지 있습니다. 짚어보겠습니다.

1. 버튼에 이미지 넣기!

Xaml에서 마이크로소프트가 제공하는 버튼을 넣으면

이렇게 나옵니다. 깔끔하긴한데 그렇게 이쁘? 지는 않는것 같습니다.

그리고 요즘 UI나 UX를 중요시 하는 시대라서 그런지 아마 저것을 그냥 쓰는 회사도 많이 없을거 같네요

그럼 어떻게 해야 할까요?

자 먼저 위의 버튼을 xaml 파일로 본다면

1
 <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="176,198,0,0" VerticalAlignment="Top" Width="182" Height="102"/>
cs

이렇게 나옵니다. 이름도 버튼 써있는 것도 버튼 그럼 우리 첨부파일중에 가위를 버튼이미지로 해보겠습니다.

1
2
3
4
5
6
7
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="176,198,0,0" VerticalAlignment="Top" Width="182" Height="102">
            <Button.Template>
                <ControlTemplate>
                    <Image Source="Assets/Scissor.png"/>
                </ControlTemplate>
            </Button.Template>
        </Button>
cs

버튼 사이에 버튼 템플릿이라는 것을 넣고 더해서 컨트롤 템플릿을 넣으면 이미지소스를 통해서 이미지모양 버튼을 만들 수 있게 됩니다.

그럼 버튼이 어떻게 나오나 볼까요?


이렇게 칙칙한 회색 버튼이 가위로 바뀌었습니다! 버튼 사이에 템플릿 넣기! 기억해 둡시다

2. 이벤트시 그림 나오게 하기

우리 버튼 이벤트( 버튼을 클릭했을 때) 어떻게 했는지 기억 나시나요?

저버튼을 두번 클릭하기!

1
2
3
4
private void button_Click(object sender, RoutedEventArgs e)
        {
 
        }
cs

그럼 이렇게 메서드가 생기죠? 자 여기서 생각을 해봅시다. 우리가 버튼을 템플릿으로 만들었을때 이미지소스 즉 위치를 컴퓨터가 찾을수 있도록 해주었죠?

그럼 저 메서드 안에서 이미지 소스를 알려주어야 하지 않을까요? 즉 이미지를 보여주는 곳에 이미지 소스를 알려주면 되지 않을까요?

네 가능합니다.! 먼저 저 앱에서 ToolBox에서 이미지를 원하는 곳에 위치 시켜봅시다.

이미지를 보여주는것에 사용할 레고 세트를 사야합니다

using Windows.UI.Xaml.Media.Imaging;

를 추가 시켜 줍시다 그래야 Bitmap이라는 클래스를 이용해서 이미지를 보여줄수 있어요!

자 그럼 소스를 적어봅시다.

1
 image.Source = new BitmapImage(new Uri("ms-appx:///Assets/Scissor.png", UriKind.Absolute));
cs

이 한줄이면 버튼을 누르면 그것이 바로 Image가 위치한 화면에 뙇! 하고 나옵니다.

소스를 뜯어보면 image의 Source를 정해줄게요! 라는 것을 시작으로 비트맵 클래스의 uri를 정해주는 겁니다.

ms-appx는 Microsoft의 앱 데이터들을 말해주는 것이고요 urikind.absolute 보니까 감이 오지 않나요?

uri경로를 절대경로로 하겠다는 뜻입니다!


자 이렇게 그림 가위바위 보를 만들기 위한 그림과 요소들을 알아보았구요! 혼자 가위바위보를 만들어 봅시다!


우리 로또 번호을 universal app으로 만들어 봅시다

먼저 로또번호가 나와야할 Textblock이 하나 필요하겠네요

두번째 로는 버튼이 필요할 것 같네요 버튼을 누를때 마다 새로운 로또 번호를 생성하도록 만들어 보겠습니다

첫번째로는 xaml 파일로 버튼과 텍스트 블록을 만들어 줍니다. 위치나 크기 등등은 마음대로 해보세요

이렇게 위치도 바꾸어 보고 만져보면서 xaml에 더 나아가 윈도우앱에 익숙해집니다!



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<Page
    x:Class="uniappTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:uniappTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
 
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Margin="0,0,-647,0">
        <Button x:Name="button" Content="로또 번호 생성하기" HorizontalAlignment="Left" Margin="675,188,0,0" VerticalAlignment="Top" Click="button_Click"/>
        <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="148,188,0,0" TextWrapping="Wrap" Text="로또 번호 생성기" VerticalAlignment="Top" Width="522" Height="32"/>
 
 
    </Grid>
</Page>
 
cs

 저같은 경우는 텍스트 블록을 하나두고 로또번호 생성기라고 처음에 넣어줄겁니다

그냥 하얀 화면에 버튼만 보인다면 심심하니까요?

그리고 그 옆에 버튼을 하나 두어서 누를때 마다 새로운 로또번호가 나오게 할 것 입니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
 
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
 
namespace uniappTest
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        int[] number;
        Random my_rand;
        public MainPage()
        {
            number = new int[7];
            my_rand = new Random();
            this.InitializeComponent();
        }
 
        private void button_Click(object sender, RoutedEventArgs e)
        {
            MakeNumber();
            textBlock.Text = " "// 초기화 전에 있던 거 지우기
            
           
            for (int i = 0; i < number.Length;i++)
            {
                
                if (number.Length-1==i)
                {
                    textBlock.Text += " 보너스 번호는 " + number[number.Length - 1];
                }
                else
                {
                    textBlock.Text += " " + number[i];
                }
            }
        }
        void MakeNumber()
        {
            int a;
            for (int i = 0; i < number.Length; i++)
            {
                a = my_rand.Next(145);
                if (true == CheckSame(i, a))
                {
                    number[i] = a;
                }
                else
                {
                    i--;
                }
            }
 
        }
        bool CheckSame(int index,int value)
        {
            for (int i = 0; i < index; i++)
            {
                if (value == number[i])
                {
                    return false;
                }
            }
            return true;
        }
       
    }
}
 
cs


나머지는 앞에서 콘솔로 만들었던 것과 같습니다! 조금 달랐던점은 제가 주석으로 표시를 해두었으니 참고하시면서

꼭 자기손으로 만들어 보시길 바랍니다!


실행화면










+ Recent posts