1. 의미
- 큐(Queue)의 사전적 의미는 무엇을 기다리기 위해 서는 줄, 대기열입니다.
예를들어 우리가 게임을 할 때 '큐를 잡는다, 큐를 기다린다'라는 말의 큐는 바로 줄, 대기열을 의미합니다. 우리가 줄을 서면 가장 앞에있는 사람(가장 먼저 들어온 데이터)이 가장 먼저 들어가죠? 이러한 구조를 선입선출(First In First Out; FIFO)구조라고 합니다. 

2. 연산
- 일반적으로 큐 자료구조의 앞을 Front, 뒤를 Rear라고 칭합니다. 그림으로 표현하면 다음과 같습니다.


큐가 비어있는 상태를 front == rear(같음) 상태로 표현합니다.
(초기화시 front = rear = 0으로 초기화)



삽입(Enqueue)연산은 rear의 위치에 데이터를 삽입하고 rear의 위치를 1 증가 시켜줍니다.



삭제(Dequeue)연산은 front 위치의 데이터를 반환하고 front의 위치를 1 증가 시켜줍니다.
이러면 front와 rear가 같은 값이 되므로 다시 큐가 비어있는 상태가 됩니다.



큐의 끝(rear)가 배열의 마지막을 가리키고있는 상태가 큐가 가득 찬 상태입니다.
이렇게 큐를 배열로 구현했을 경우 0번 인덱스는 사용하지 않는 메모리가 되었습니다.
물론 고정적인 배열의 크기도 문제가 됩니다.
이를 해결하기 위해 원형 큐, 링크드 리스트로 구현한 큐... 등 여러가지 큐가 존재합니다.

3. 사용
프로세스 관리
운영체제(OS)의 작업 큐
프린터 출력의 문서 대기...등 
입력된 시간 순서대로 처리해야하는 모든 상황에 거의 큐가 사용됩니다.

4. 구현
배열로 구현한 큐)
#include <iostream> 
using namespace std;

class queue
{
private:
     int *queue_arr; // 큐 배열(동적 할당을 위해 포인터로 선언) 
     int queue_size; // 큐의 크기 
     int 
front, rear;

public:
     queue() // 디폴트 생성자 함수 
     {
          
front = 0; rear = 0// front와 rear 위치를 0으로 초기화
          queue_size = 5// 매개변수 없이 객체 생성 시 스택 크기 5로 지정 
          queue_arr = new int[queue_size]; // 배열 동적 할당 
          for (int i = 0; i < queue_size; i++)
          {
               queue_arr[i] = 0// 큐의 배열은 모두 0으로 초기화 
          }
     }
     queue(int 
size// 생성자 함수 
     {
          front = 0; rear = 0// front와 rear 위치를 0으로 초기화
          queue_size = 
size// 입력한 매개변수 크기만큼 스택 크기 지정 
          queue_arr = new int[queue_size]; // 배열 동적 할당 
          for (int i = 0; i < queue_size; i++)
          {
               queue_arr[i] = 0// 큐의 배열은 모두 0으로 초기화 
          }
     }
     ~queue() // 소멸자 함수 
     {
          delete[] queue_arr;
     }
     void enqueue(int data) // 삽입 함수 
     {
          if (queue_is_full()) // 큐가 가득 차 있는 경우 
          {
               cout << "큐가 가득 차 있습니다." << "\n";
               return// 함수 종료 
          }
          else // 아닐 경우
          {
               queue_arr[rear++= data;
               // 큐 배열 rear 위치의 데이터를 삽입 후 rear의 크기 1 증가
               // 위 코드가 이해가지 않는다면 후위 증감 연산자에 대해 공부할 것
               cout << "데이터 삽입 성공!" << "\n";
          }
     }
     void dequeue() // 삭제 함수 
     {
          if (queue_is_empty()) // 큐가 비어있는 경우 
          {
               cout << "큐가 비어있습니다." << "\n";
               return// 함수 종료 
          }
          else // 아닐 경우 
          {
               cout << "반환 된 데이터 : " << queue_arr[front<< "\n"// 데이터 반환 
               queue_arr[front++= 0
               // 큐 배열 front 위치의 데이터를 삭제 후 front 크기 1 증가
          }
     }
     bool queue_is_empty() // 큐가 비어있는지 확인 함수 
     {
          if (front == rear) // front와 rear가 같은 위치라면
               return true;
          else // 아닐 경우 비어있지 않음 
          return false;
     }
     bool queue_is_full() // 큐가 가득 차 있는지 확인 함수 
     {
          if (rear == queue_size - 1// rear가 큐 배열의 마지막 위치라면
               return true;
          else // 아닐 경우 가득 차 있지 않음 
               return false;
     }
     void print_queue() // 큐 배열 전체 출력 함수 
     {
          cout << "Queue : [ ";
          for (int i = 0; i < queue_size; i++)
          {
               if (i != queue_size - 1)
               {
                    cout << queue_arr[i] << " , ";
               }
               else
               {
                    cout << queue_arr[i];
               }
          }
     cout << " ] " << "\n";
     cout << "front 위치 : " << front << "\n";
     cout << "rear 위치 : " << rear << "\n";
     }
};

int main()
{
     queue *que;
     int input_size;
     cout << "큐 배열 크기 입력 : ";
     cin >> input_size;
     if (input_size <= 0)
     {
          cout << "잘못 된 입력입니다. 디폴트 사이즈(5)로 생성합니다." << "\n";
          que = new queue();
     }
     else
     {
          que = new queue(input_size);
     }
     while (1)
     {
          int input;
          cout << "\n" << "[명령어 입력]" << "\n";
          cout << "1. ENQUEUE " << "\n" << "2. DEQUEUE " << "\n" << "3. PRINT " << "\n" << "4. EXIT : ";
          cin >> input;
          switch (input)
          {
          case 1:
               int input_data;
               cout << "삽입 할 데이터를 입력하세요 : ";
               cin >> input_data;
               que->enqueue(input_data);
               break;
          case 2:
               que->dequeue();
               break;
          case 3:
               que->print_queue();
               break;
          case 4:
               cout << "프로그램을 종료합니다." << "\n";
               return 0;
          default:
               cout << "잘못 된 입력입니다. 다시 입력해 주세요" << "\n";
          }
     }     
}

질문 사항은 댓글로 남겨주세요!



1. 의미
- 스택 자료구조는 아래가 막혀있는 긴 통에 물건을 층층이 쌓아둔 상태로 보시면 됩니다. 
예를들어 물건을 쌓기위해서는 현재 쌓여있는 물건 중 가장 위쪽에 쌓일 것이고, 꺼내기 위해서는 현재 쌓여있는 물건 중 가장 위쪽 물건이 꺼내질 것입니다. 이러한 구조를 선입후출(First In Last Out; FILO)또는 후입선출(Last In First Out; LIFO) 구조라고 칭합니다.

2. 연산
- 스택 자료구조의 연산(삽입, 삭제, 읽기)은 모두 스택의 꼭대기에서 일어납니다. 스택의 꼭대기를 가리키는 변수를 통상적으로 top이라고 합니다.


top이 -1을 가리키고 있는 상태가 스택이 비어있는 상태입니다.
(이해를 돕기위해 -1 인덱스를 표기한 것이지 배열의 인덱스는 0에서 시작합니다.)

삽입(push) 연산은 top이 가리키는 위치를 1 증가시키고, 그 위치에 데이터를 삽입합니다.


top이 인덱스 맨 끝을 가리키고 있는 상태가 스택이 가득 찬 상태입니다.
(인덱스 맨 끝은 스택 사이즈 -1입니다. 인덱스가 0부터 시작하기 때문)


삭제(pop) 연산은 top이 가리키는 위치의 데이터를 반환하고, 위치를 1 감소합니다.

3. 사용
- 스택은 컴퓨터 구조에서 다음과 같이 다양하게 사용됩니다. 

브라우저에서 이전페이지, 다음페이지 이동
에디터에서 실행취소, 다시실행
괄호검사
역순문자열 만들기
후위 표기법 수식의 연산 등...

아래의 구현방법을 통해 실제 스택 사용 예를 직접 구현해 보는것도 자료구조의 이해와 실력 향상에 도움이 될 것입니다.

4. 구현
C++ Class를 이용해 스택 자료구조를 배열로 구현했습니다.

#include <iostream> 
using namespace std; 

class stack 

private : 
     int *stack_arr; 
// 스택 배열(동적 할당을 위해 포인터로 선언) 
     int stack_size;
 // 스택의 크기 
     int top = -1; 
// top은 -1로 초기화  

public : 
     stack() 
// 디폴트 생성자 함수 
     
          stack_size = 5; 
// 매개변수 없이 객체 생성 시 스택 크기 5로 지정 
          stack_arr = new int[stack_size]; 
// 배열 동적 할당 
          for (int i = 0; i < stack_size; i++) 
          
               stack_arr[i] = 0;
 // 스택의 배열은 모두 0으로 초기화 
          
     
     stack(int size) 
// 생성자 함수 
     
          stack_size = size; 
// 입력한 매개변수 크기만큼 스택 크기 지정  
          stack_arr = new int[stack_size]; 
// 배열 동적 할당 
          for (int i = 0; i < stack_size; i++) 
          
               stack_arr[i] = 0; 
// 스택의 배열은 모두 0으로 초기화 
          
     
     ~stack() 
// 소멸자 함수 
     
          delete[] stack_arr; 
     
     void push(int data) 
// 삽입 함수 
     
          if (stack_is_full()) 
// 스택이 가득 차 있는 경우 
          
               cout << "스택이 가득 차 있습니다." << "\n"; 
               return;
 // 함수 종료 
          
          else 
// 아닐 경우 정상 작동 
          
               top++; 
// top 위치 1 증가 
               stack_arr[top] = data; // 데이터 삽입 
               cout << "데이터 삽입 성공!" << "\n"; 
          
     
     void pop() 
// 삭제 함수 
     
          if (stack_is_empty()) 
// 스택이 비어있는 경우 
          
               cout << "스택이 비어있습니다." << "\n"; 
               return; 
// 함수 종료 
          
          else 
// 아닐 경우 
          
               cout << "반환 된 데이터 : " << stack_arr[top] << "\n"; 
// 데이터 반환 
               stack_arr[top] = 0; 
// 데이터 삭제 
               top--; 
// top 위치 1 감소 
          
     
     int peak() 
// 현재 꼭대기 위치 확인 함수 
     
          return stack_arr[top]; 
     
     bool stack_is_empty()
 // 스택이 비어있는지 확인 함수 
     
          if (top == -1)
 // top이 -1을 가리키면 비어있음 
               return true;  
          else 
 // 아닐 경우 비어있지 않음 
               return false; 
     
     bool stack_is_full() 
// 스택이 가득 차 있는지 확인 함수 
     
          if (top == stack_size - 1) 
// top이 인덱스 마지막을 가리키면 가득 차 있음 
               return true; 
          else 
 // 아닐 경우 가득 차 있지 않음 
               return false; 
     
     void print_stack() 
// 스택 전체 출력 함수 
     
          cout << "STACK : [ "; 
          for (int i = 0; i < stack_size; i++) 
          
               if (i != stack_size - 1) 
               
                    cout << stack_arr[i] << " , "; 
               
          else 
          
               cout << stack_arr[i]; 
          
     
     cout << " ] " << "\n"; 
     cout << "top 위치 : " << top << "\n"; 
     
}; 

int main()  

     stack *stk; 
     int input_size; 
     cout << "스택 크기 입력 : "; 
     cin >> input_size; 
     if (input_size <= 0) 
     
          cout << "잘못 된 입력입니다. 디폴트 사이즈(5)로 생성합니다." << "\n"; 
          stk = new stack(); 
     
     else 
     
          stk = new stack(input_size); 
     
     while (1) 
     
          int input; 
          cout << "\n" << "[명령어 입력]" << "\n"; 
          cout << "1. PUSH " << "\n" << "2. POP " << "\n" << "3. PEAK "  
          << "\n" << "4. PRINT " << "\n" << "5. EXIT : "; 
          cin >> input; 
          switch (input) 
          
          case 1: 
               int input_data; 
               cout << "삽입 할 데이터를 입력하세요 : "; 
               cin >> input_data; 
               stk->push(input_data); 
               break; 
          case 2: 
               stk->pop(); 
               break; 
          case 3: 
               cout << "현재 top 위치의 데이터 : " << stk->peak() << "\n"; 
               break; 
          case 4: 
               stk->print_stack(); 
               break; 
          case 5: 
               cout << "프로그램을 종료합니다." << "\n"; 
               return 0; 
          default : 
               cout << "잘못 된 입력입니다. 다시 입력해 주세요" << "\n"; 
          
     
}


질문 사항은 댓글로 남겨주세요!




본 게시글은 Visual Studio 2017 및 OpenCV 2.4.10 버전 기준으로 작성되었음을 알려드립니다.


* 설치하기
1. https://opencv.org/releases.html 링크에 접속합니다.

2. 2.4.10 버전의 win pack을 다운받고 압축을 풉니다. 
   (경로 상관없이 외워두시기만 하면 됩니다.)

3. Visual Studio 2017을 실행합니다.

4. C# Windows Forms 앱으로 프로젝트를 생성합니다.

4-1. 프로젝트를 한번 실행해줍니다.(Ctrl + F5)

5. 생성한 c# 프로젝트 폴더로 이동합니다.

6. 프로젝트 폴더 - bin - debug 에 2번에 풀었던 압축 파일을 모두 복사해줍니다.

7. 다시 Visual Studio로 돌아와서 솔루션 탐색기 - 참조 - 우클릭 - 참조 추가

8. 아래측 찾아보기 버튼을 누르고 6번에 복사해준 폴더로 이동합니다.

9. OpenCV ~ 5개의 dll 파일을 선택하고 추가해줍니다.


10. 확인을 누르면 Visual Studio 2017 C# 환경에서 OpenCV 라이브러리를 사용할 
     준비가 완료되었습니다.


질문사항은 댓글로 달아주세요!



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

C# 기초다지기 - 문자열  (2) 2018.11.07
C# 기초다지기 - 배열  (1) 2018.11.06
C# 기초다지기 - 상수  (0) 2018.11.06
C# 기초다지기 - 캡슐화  (0) 2018.11.05
C# 기초다지기 - 프로그램 구조  (0) 2018.11.05
C# 기초다지기 - 변수  (0) 2018.11.05
C# DB연동  (1) 2018.08.29
[C#] 유니코드 한글로 변환하기  (0) 2018.08.22


* 개발환경
개발 툴 : Visual Studio 15.0 (2017)
개발 언어 : C#
데이터베이스 : MySQL 5.7

* 데이터베이스 테이블
Table 1 : User - Num(PK), ID, PW, Manager
Table 2 : Data - Code, Date, User(FK)

* 기능
- 데이터 추가, 삭제, 수정, 검색(JDBC를 통한 Java-MySQL Database연동)
- 사용자 추가, 삭제, 목록(DB연동)
- 파일 입출력(Local)

* 주요 소스코드
- 기본 설명은 주석으로 처리했습니다.

1) 로그인
private void button_Login_Click(object sender, EventArgs e) { 
            String id = textBox4.Text; 
            String password = textBox3.Text; 
 // 입력받은 ID와 PASSWORD를 변수에 저장 
            int logInCheck = 0; 
            scon = new MySqlConnection(url); 
            scom = new MySqlCommand(); 
            scom.Connection = scon; 
 // SELECT 쿼리문(입력받은 ID,PASSWORD를 DB내에서 검색) 
            scom.CommandText = "SELECT * FROM user"; 
            try   { 
                scon.Open(); 
                sdr = scom.ExecuteReader(); 
                while (sdr.Read())   { 
                    String getId = sdr["id"].ToString(); 
                    String getPassword = sdr["password"].ToString(); 
                    String getManager = sdr["manager"].ToString(); 
 // 입력한 ID와 PASSWORD가 일치하는 내용이 있을 때 
                    if (id.Equals(getId) && password.Equals(getPassword))   { 
                        if (getManager.Equals("True")) 
   {   // 관리자가 로그인 할 경우
                            MessageBox.Show("[관리자] " + id + " 님 환영합니다.", "로그인 성공"); 
                        } 
                        else  

                        { // 사용자가 로그인 할 경우 
                            MessageBox.Show("[사용자] " + id + " 님 환영합니다.", "로그인 성공"); 
                        } 
                        logInCheck = 1; 
                        nowId = id; 
                       
 // 저장 경로 설정 
                        saveFolder = @"D:\BarcodeDataManager\" + textBox4.Text + @"\" 
                                     + nowTime.Split('.')[0] + @"년\" + nowTime.Split('.')[1] + @"월\"; 
                        saveRoute = saveFolder + nowTime.Split('.')[2].Split(' ')[0] + "일.txt"; 
                        textBox2.Text = saveRoute; 
                        dataGridView1.Columns[0].HeaderText = "시간"; 
                        dataGridView1.Columns[1].HeaderText = "바코드"; 
                        break; 
                    } 
                } 
                if (logInCheck != 1) 
// 입력받은 ID와 PASSWORD가 일치하지 않는 경우 
                { 
                    MessageBox.Show("ID 또는 PASSWORD를 확인해주세요", "로그인 실패"); 
                    textBox3.Clear(); 
                    textBox4.Clear(); 
                    textBox4.Focus(); 
                } 
            } 
            catch (Exception ex) 
            { 
                MessageBox.Show(ex.Message, "오류발생!"); 
            } 
            finally 
            { 
                scon.Close(); 
                textBox1.Focus(); 
            } 
 }

2) 바코드 입력
private void textBox_Barcode_KeyUp(object sender, KeyEventArgs e)   { 
            
// 엔터키 입력 시 
            if (e.KeyCode == Keys.Enter) 
            { 
                
// 입력 란이 비어있을 경우 
                if (textBox1.Text.Equals("")) 
                { 
                  
  // 함수 종료 
                    return; 
                } 
                String barcode = textBox1.Text; 
                textBox1.Text = ""; 
               
 // Database 내 중복검사 함수 호출 
                if (isOverlap(barcode)) 
                { 
                    
// Database 내 데이터 입력 함수 호출 
                    insertDatabase(barcode); 
                  
  // 로컬 컴퓨터 내 txt파일 저장 
                    dataFileWriter(barcode); 
                    if (checkBox1.Checked) // 기록여부 체크박스 확인 
                    { 
                        String[] Row = { nowTime, barcode }; 
                        dataGridView1.Rows.Add(Row); 
                        dataGridView1.FirstDisplayedScrollingRowIndex = 
                        dataGridView1.Rows.Count - 1;
 // DataGridView 자동 스크롤 
                    } 
                } 
                
// Data 중복 시 
                else 
                { 
                   
 // 함수 종료 
                    return; 
                } 
            } 
}


3) 데이터 추가(관리자용)
private void button_Data_Insert_Click(object sender, EventArgs e)  { 
            String barcode = textBox1.Text; 
            if(barcode.Equals("")) 
            { 
                MessageBox.Show("입력을 확인해주세요"); 
                return; 
            } 
            String time; 
            String user; 
           
 // 현재 시간 사용 체크 시 
            if(checkBox1.Checked) 
            { 
                time = Form1.nowTime; 
            } 
            
// 아닐 시 입력된 dateTimePicker에서 값을 받아온다. 
            else 
            { 
                time = dateTimePicker1.Value.ToString("yyyy.MM.dd HH:mm:ss"); 
            } 
            
// 현재 사용자 사용 체크시 
            if(checkBox2.Checked) 
            { 
                user = Form1.GetId(); 
            } 
           
 // 아닐 시 입력된 콤보박스에서 값을 받아온다. 
            else 
            { 
                user = comboBox1.SelectedItem.ToString(); 
            } 
            
// 데이터 중복 확인 
            if(Form1.isOverlap(barcode)) 
            { 
                Form1.scon = new MySqlConnection(Form1.url); 
                Form1.scom = new MySqlCommand(); 
                Form1.scom.Connection = Form1.scon; 
               
 // INSERT 쿼리문 
                Form1.scom.CommandText = "INSERT INTO datalist (code, serial, user) VALUES ('" 
                    + barcode + "','" + time + "','" + user + "');"; 
                try 
                { 
                    Form1.scon.Open(); 
                    Form1.sdr = Form1.scom.ExecuteReader(); 
                    MessageBox.Show("데이터가 입력되었습니다."); 
                } 
                catch (Exception ex) 
                { 
                    MessageBox.Show(ex.Message); 
                } 
                finally 
                { 
                    Form1.scon.Close(); 
                    this.Close(); 
                } 
            } 
            
// 데이터 중복 시 
            else 
            { 
               
 // 함수 종료 
                textBox1.Focus(); 
                return; 
            } 
 }


4) 데이터 중복검사
public static bool isOverlap(String inputBarcode)   { 
            scon = new MySqlConnection(url); 
            scom = new MySqlCommand(); 
            scom.Connection = scon; 
           
 // SELECT 쿼리문(입력받은 Barcode를 DB내에서 검색) 
            scom.CommandText = "SELECT * FROM datalist"; 
            try 
            { 
                scon.Open(); 
                sdr = scom.ExecuteReader(); 
                while (sdr.Read()) 
                { 
                    String getSerial = sdr["serial"].ToString(); 
                    String getCode = sdr["code"].ToString(); 
                    if (inputBarcode.Equals(getCode)) 
                    { 
                        MessageBox.Show("[ " + getSerial + " ] " + inputBarcode + 
                                        "은 이미 중복되었습니다.", "데이터 중복"); 
                        return false; 
                    } 
                } 
            } 
            catch (Exception ex) 
            { 
                MessageBox.Show(ex.Message, "오류발생!"); 
            } 
            finally 
            { 
                scon.Close(); 
            } 
            return true; 
 }


5) 파일쓰기(로컬 컴퓨터에 따로 저장)
 private void dataFileWriter(String barcode) { 
            if(checkBox2.Checked == true) 
// 저장 여부 체크박스 확인 
            { 
                DirectoryInfo di = new DirectoryInfo(saveFolder); 
                if (di.Exists == false)
 // 지정된 경로에 폴더가 있는 지 확인 
                { 
                    di.Create(); 
// 폴더 생성 
                } 
                
// 파일쓰기 (true 옵션 : 파일 맨 끝에 덧붙여 쓰기) 
                using (StreamWriter outputFile = new StreamWriter(saveRoute, true)) 
                { 
                    outputFile.WriteLine("[" + nowTime + "] " + barcode); 
                } 
            }   
}

* 실행화면


- 화면구성 
기록 란 리스트 ) DataGridView
* 다음 함수를 통해 DataGridView PostHeader에 index를 추가
        private void dataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e) 
        { 
            if (e.RowIndex >= 0) 
            { 
                string NumberingText = (e.RowIndex + 1).ToString(); 

               
 // 글자 사이즈 구하기. 
                SizeF stringSize = e.Graphics.MeasureString(NumberingText, Font); 

               
 // 글자에 맞춰 좌표계산.  
                PointF StringPoint = new PointF 
                ( 
                    Convert.ToSingle(dataGridView1.RowHeadersWidth - 3 - stringSize.Width), 
                    Convert.ToSingle(e.RowBounds.Y) + dataGridView1[0, e.RowIndex].ContentBounds.Height * 0.3f 
                ); 

                
// 문자열 그리기. 
                e.Graphics.DrawString 
                ( 
                    NumberingText, 
                    Font, 
                    Brushes.Black, 
                    StringPoint.X, 
                    StringPoint.Y 
                ); 
            } 
        }

바코드 입력 란) TextBox - USB를 통해 바코드 입력 시 바코드 입력 후 자동 Enter키 입력
현재시간) Label - 쓰레드를 통해 1초마다 현재시간 갱신(바코드 입력 시간 저장)

** 바코드 입력 란은 항상 포커스가 유지되어야 하기 때문에 쓰레드 또는 버튼 이벤트에 포커스를 유지하는 함수를 호출 해 주어야 합니다 **

질문 사항은 댓글로 남겨주세요






[C# DLL 파일 생성 및 C++ 연동법 ]

1. C#에서 DLL파일 생성 

0) VS 관리자 권한으로 실행! 
1) 새 프로젝트 - 클래스 라이브러리(.NET Framework) 
2) using System.Runtime.InteropServices; 코드 추가 
3) 프로젝트 우클릭 - 속성 - 응용프로그램 - 어셈블리 정보 - 어셈블리를 COM에 노출 체크 
4) 빌드 - COM interop 등록 체크 
5) 도구 - GUID 만들기 - 5번 항목 복사 
6) 클래스 위에 GUI 붙여넣기 
7) Class를 Interface로 변경 
8) Interface에 메소드 선언 
9) 아래(같은 레벨)에 Interface를 상속받은 클래스 선언(사용될 클래스) 
10) 쓰레드 사용시 반드시 static으로 선언 
11) C# 코드 빌드 
12) 프로젝트 내 \bin\debug\'프로젝트명'.dll 생성 확인 
13) VS 개발자 명령 프롬프트 관리자 권한으로 실행! 
14) 디렉토리를 프로젝트\bin\debug\로 변경 
15) regasm '파일이름'.dll /tlb:'파일이름'.tlb 실행 

2. C++에서 C# DLL파일 사용 

0) VS 관리자 권한으로 실행! 
1) include 밑에 #import "파일이름.tlb" no_namespace named_guids 추가 
2) 'C#클래스명' *'객체이름' = NULL; 
3) CoInitialize(NULL); 
4) HRESULT hr = CoCreateInstance(CLSID_'인터페이스명', NULL, CLSCTX_INPROC_SERVER, IID_'클래스명', reinterpret_cast<void**>(&'객체이름')); 
5) if (SUCCEEDED(hr)) 후 '객체이름'->'메소드명' 으로 사용

'C, C++' 카테고리의 다른 글

C/C++ 구조체 사용법 및 예제  (1) 2018.10.08
C/C++ 배열 사용법  (0) 2018.10.05
C 파일처리  (0) 2018.10.02
C++ 벡터 사용법  (2) 2018.09.26
C언어 포인터  (8) 2018.09.25
C++ 자바 상속 비교  (0) 2018.09.08
C 랜덤 - 난수 생성하기  (7) 2018.09.06
C++ String 문자열 사용법 정리  (0) 2018.08.20

to Top