반응형

C# Socket : 고정 구조체 만들기

알게된 배경

 C++로 작성된 서버 혹은 PC와 통신을 하기 위해서는 일반적으로 고정된 크기의 Head와 고정 혹은 가변의 Body로 나누어서 통신을 하는 경우가 많다. C/C++에서는 Struct를 고정된 크기로 할당하는 것이 가능한 반면 C#에서는 별도의 코딩이 필요로 하다.

 이는 기본적으로 C#에서는 배열을 new 키워드를 통해서 정의 및 초기화를 했기때문에 struct에서는 사용이 불가능하다(반면 클래스에서는 사용가능하다).


C/C++의 고정 Struct

 그냥 배열로 선언을 해주면 된다. 아래의 SHead의 크기는 대략 40바이트가 된다. C에서는 그냥 선언해주면 되지만, C++의 경우에도 컴파일에 따라서 추가 선언을 해줘야 한다. C++에 대해서 추후 링크를 추가한다.

// head.hpp
struct SHead
{
    char name[8];
    unsigned char headType;
    char hostname[31];
};



C# unsafe

지금은 폐지된 방법이다. 초기에 불편하자 급조한 티가 난다. 참조문서는 지금도 가이드라인에 있다. 폐지된 만큼 가이드 라인에 맞게 작성해도 에러로 표시된다. 폐지된 방법은 아니고 컴파일 옵션에서 안전하지 않은 코드 컴파일 설정을 바꿔서 실행할 수 있다. C 스타일의 코딩을 자주 해야 한다면, 컴파일 옵션을 풀고 작성하는 것이 코드가 더욱 간결하다. 하지만, 키워드에서 알 수 있듯이 안전하지 않다. (그리고 마소에서 쓰지 않도록 하려고 일부러 쓰기 어렵게 만들어 놓은 방법이기도 하다)


 unsafe가 위험한 이유는 GC가 unsafe로 선언된 곳은 메모리 해제를 하지 않는다.

namespace sock
{
    public struct unsafe SHead
    {
        public Byte fixed name[8];
        public Byte headType;
        public Byte fixed hostname[31];
    }
}




C# Marshal

권장하는 방법이다. 시그니처를 이용해서 배열의 크기를 정해주는 방식이다. 사용하기 위해서는 using System.Runtime.InteropServices; 를 선언하거나 전부 적어주면 된다. pack 옵션 값은 메모리 처리 방식을 할때 단위를 1바이트로 하겠다는 의미이다.

 이러한 키워드를 추가 하지 않으면, 시스템마다 차이는 있지만, 기본적으로는 8바이트를 기준으로 처리를 한다.

namespace sock
{
    [Structlayout(LayoutKind.Sequential, pack=1)]
    public struct SHead
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public Byte[] name;
        public Byte headType;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)]
        public Byte[] hostname;
    }
}



 여기서 C#에서 취급하는 특징을 보면 메모리에 배열처럼 연속으로 올릴 경우를 안전하지 않은 방법으로 취급하기 때문에 여러 번거로움이 있다. 이렇게 번거롭게 만든 이유는 가능하면 사용하지 말라는 의도가 있다는 것으로 보인다. 그래도 소켓 프로그램 쪽에서는 어쩔 수 없이 사용해야 하는 경우가 있다.

잡설

 따지고 보면 C#에서 제공하는 두가지 방법들 모두 해당 자료가 안전하지 않다는 것을 명시해주는 것이다. 속도 같은 효율도 떨어진다는 건 덤.. 이러한 이유로 C로 프로그램을 작성할 경우 시스템 이해도와 잘하는 사람과 못 하는 사람간의 차이가 심하다.


참조자료

가이드 라인 unsafe

가이드 라인 unsafe 모드 컴파일

MASN문서 Marshal Array

MSDN문서 LayoutKind

블로그 :고정크기 사용방법




반응형
반응형

C# WinForm : 문자 픽셀 측정

알게된 배경

 본의 아니게 C#으로 윈도우 기반으로 간단한 프로그램을 작성하다 보니 몇몇은 나중에 다시 찾기 힘들것 같아서 이러한 것들은 기록으로 남긴다.

 문자 픽셀의 길이 경우 윈도우에서 기본적으로 제공하는 Component 를 동적(코드로)으로 작성할 경우 Label 같은 경우 autoSize를 true로 켜도 최종 크기를 size나 width, height에 갱신이 되지 않았었기 때문에 찾은 방법이다.


매서드 원형

SizeF Graphics.MeasureString(String, Font, Int32)

실제로는 앞의 2개의 인자만 있어도 된다.



예제 소스

using System.Window.Form;
using System.Drawing;

class CustumLabel : Label
{
    public CustumLabel(Sting text)
    {
        Text = "Offline";
        var width = Graphics.MeasureString(Text, Font);
        Width = (int)Math.Ceiling(width);
    }
}


위의 소스코드로 당장 변화를 확인 할 수는 없지만, 나머지도 작성하면 길어지므로 일단은 생략한다.


참조자료

MSDN 문서 Graphics.measureString Method



반응형
반응형

C# OpenCV : nuget을 이용한 OpenCV 개발환경 구축

알게된 배경

C#의 높은 생산성을 알고 나서 OpenCV도 사용할 수 있지 않을까 해서 알아봤는데, 공식 OpenCV에서는 아직 C# 개발환경을 지원하지 않았다. 하지만, C#에서 실행이 가능하도록 옮겨 놓았다는 사실을 알게 되었다.

 친절하게도 오픈소스 설치과정이 어려울까봐 VS의 Nuget 명령어 창을 링크를 걸어줘서 이전과 달리 환경 설정의 부담이 매우 줄게 되었다.


Nuget이란?

비주얼 스튜디오에서 사용되는 오픈소스 프로젝트의 패키지를 관리(PM : Package Management)툴 이다. 프로젝트가 열린 상태에서 실행할 수 있다. 보통 도구 쪽에 잘 찾아보면 있다.


필요한 것

VS2015, OpenCV3.2


주의 할점

 OpenCV의 윈도우 버전 패키지를 다운로드를 받을 때 설치된 폴더의 opencv\build\x64\vc14\bin 이 경로를 환경변수에 등록을 해줘야 한다. 이 때 vc14는 VS2015를 의미하고 vc13은 VS2013 이런식으로 버전을 의미하기 때문에 이를 참고해서 다운로드 받아야 한다.

 현시점에서는 vc14가 최대 지원 버전이기 때문에 VS2015에서 개발을 진행해야 햔다.


 환경변수 잡는 경로는 자신이 압축을 푼 폴더내에서 build\x64\vc14\bin 폴더가 연결되면된다. 이는 실행에 필요한 조건이다. openCvSharp라이브러리만 가지고는 OpenCV를 실행할 수 없는 것으로 보인다.


Nuget으로 openCvSharp 설정잡기

 VS2015를 실행해서 프로젝트를 생성한다. 이후 [도구] -> [Nuget 패키지 관리자] -> [패키지관리자 콘솔] 을 실행하면 하단에 Nuget 커멘드 창이 생성된다.


Install-Package OpenCvSharp3-AnyCPU -Version 3.2.0.20170419


 이후 열심히 개발환경을 셋팅을 해준다. 그리고 테스트용 코드를 사용해보자. 테스트에 사용할 이미지는 마음에 드는 걸로 사용해도 상관없다. 다만, 이미지는 프로젝트 솔루션 내의 Debug(Debug상태에서 설치했으므로)에 넣어주어야 된다.

 설치 커맨드는 정식 github에도 링크가 있고, NuGet에도 있다.

링크 : github OpenCVSharp

링크 : NuGet OpenCVSharp


테스트용 소스코드

프로젝트는 콘솔 앱으로 생성했다.


using OpenCvSharp;

namespace openCvTest01
{
    class Program
    {
        static void Main(string[] args)
        {
            Mat src = new Mat("lena.jpg", ImreadModes.GrayScale);
            Mat dst = new Mat();

            Cv2.Canny(src, dst, 50, 200);
            using (new Window("src image", src))
            using (new Window("dst image", dst))
            {
                Cv2.WaitKey();
            }
        }
    }
}


 만만한게 레나 사진이다(지금도 살아계실지??). 테스트용 소스코드는 github에 저자가 올린 소스코드를 그대로 옮긴 것이다. 정상적으로 2장의 이미지가 보이면 된다.


참고자료

본문중 Github 링크

반응형

'C#' 카테고리의 다른 글

C# 싱글톤 패턴 : 동적 싱글톤  (0) 2017.09.04
C# Socket : 고정 구조체 만들기  (0) 2017.07.11
C# WinForm : 문자 픽셀 측정  (0) 2017.07.06
C# : 콘솔 앱 프로젝트에서 콘솔 감추기  (0) 2017.06.22
C# : 프로퍼티(property)  (0) 2017.01.23
반응형

C# : 콘솔 앱 프로젝트에서 콘솔 감추기

알게된 배경

 프로젝트에서 윈도우 폼UI 부분은 C#이 비교적 생산성이 높다고 해서 알아보게 되었다. 특히 콘솔 앱(.NET Framework) 중에서 동적으로 UI 생성이 가능하다는 것을 알게 되었다. 아마 내 기억에는 MFC도 콘솔에서 구현은 가능하지만 정신건강상 하지 않는게 좋은걸로 알고있다. 암튼, 이를 이용해서 생성 연습을 하던중 콘솔창을 감추는 방법을 검토하면서 기록하게 되었다.

 

참조(Reference) 설정

솔루션 탐색기에서 참조에 마우스 우클릭으로 참조 추가를 선택하여 System.Windows.Forms 항목을 체크를 표시해야 된다.

 

소스코드

아직 C#이 익숙하지 않지만, Main의 마지막 2줄은 윈도우 폼을 생성하는 코드이다.

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace winform
{
    class MainApp : Form
    {         
        [DllImport("kernel32.dll")]
        static extern IntPtr GetConsoleWindow();
        
        [DllImport("user32.dll")]
        static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
        
        const int SW_HIDE = 0;
        const int SW_SHOW = 5;
        
        static void Main(string[] args)
        {
            var handl = GetConsoleWindow();
            ShowWindow(handl, SW_HIDE);
                
            MainApp form = new MainApp();
            Application.Run(form);
        }
    }
}

 

 실행을 해보면 콘솔이 생겼다가 윈도우 폼이 생성되면서 콘솔창이 사라지는 것을 확인할 수 있다. 이는 폼 클래스내부에 메인이 함수가 있어서 발생하는 듯하다. 반드시 위의 소스처럼 사용할 필요는 없고 다만, 각 코드의 위치때문에 기록을 남긴다.

 

참고자료

스택오버플로어

 

 

반응형
반응형

C# : 프로퍼티(property)

프로그래밍 언어에서 클래스가 등장한 이후, 코딩을 하다보면 항상 반복적으로 작성되는 메서드(C/C++ 계열에서는 함수)를 간편하게 작성하기 위한 문법을 제공한다. 그중 프로퍼티는 set/get에 대해서 간단하게 정의를 해주는 문법이다.


프로퍼티 문법 예시

class Property
{
    int tmp;

    public int tmp
    {
        get { return tmp; }
        set { tmp = value; }
    }
    // ...
}

Property ppy = new Property();
ppy.tmp = 5;        // 쓰기
int a = ppy.tmp;   // 읽기

예시에서 사용된 set의 value 는 C# 언어상 제공되는 예약어다. 또한 읽기만 가능한 멤버 변수로 만들 수도 있다.


예시의 컴파일러 결과

class Property
{
    int tmp;

    public void setTmp(int value)
    {
        this.tmp = value;
    }

    public int getTmp()
    {
        return this.tmp;
    }
    // ...
}

Property ppy = new Property();
ppy.setTmp(5);    // 쓰기
int a = ppy.getTmp()    // 읽기

위의 추가 예제처럼 실제로는 C/C++에서 흔히 볼 수 있는 형태로 변환이 된다. 즉, 프로퍼티는 코딩수를 줄이고, 직관적으로 알 수 있게 해주는 도와주는 형태의 문법이다.



(5.0 부터 지원되는) 프로퍼티 간략화

이전 버전방식이 유효한 상태에서 어차피 value값이 정해져 있는 경우에는 아예 키워드 get, set 만으로도 유효하다.

예시)

class Property
{
    int tmp;

    public int tmp
    {
        get;
        set;
    }
    // ...
}




반응형

+ Recent posts