Scilab함수는 다음과 같이 세 가지 상태가 있다.


➊ 컴파일이 안 된 상태

➋ 컴파일이 된 상태

➌ 프로파일링을 위한 구문이 들어간 상태로 컴파일 된 상태


만약 콘솔에서 함수를 정의한다면 endfunction이 입력되는 순간 컴파일이 된 후 workspace에 함수가 로드된다. 따라서 그 즉시로 호출하여 사용할 수 있다. 파일로 저장된 Scilab함수는 그 자체로는  컴파일이 안된 상태이고 Scilab에서 이 함수를 사용하기 위해서는 반드시 컴파일한 후 workspace에 로드하여야 한다. 프로파일링(profiling)이란 함수를 실행하는데 각각의 줄(line)이 몇 번 실행되었는지 그리고 실행 시간이 얼마나 되는지를 분석하는 것을 말하며 이를 위해서는 추가적인 구문이 필요하다. 함수가 컴파일 된 것인지 아닌지를 확인하려면 type(functoin_name) 함수를 실행해보면 된다. 결과값이 11이면 컴파일이 안된 함수이고 13이면 컴파일된 것이다.


 Scilab에서 함수를 생성하는 방법은 콘솔창에서 직접 입력하는 방법 외에도 다음에 소개하는 deff()함수를 이용하는 방법과 파일(sci파일)에서 로드하는 방법이 이다.

인라인 함수

 함수를 생성하는 방법은 앞 장에서 설명한 바와 같이 콘솔창에서 직접 입력하는 방법 외에 deff()함수를 이용하여 인라인 함수(in-line function)을 생성하는 방법도 있다. 예를 들어서 다음과 같다.



deff() 함수의 첫 번째 인자는 함수 헤더이고 두 번째 인자는 함수의 본체인데 반드시 문자열로 입력해야 한다. 세 번째 인자는 선택 사항인데 함수를 컴파일할 것인지 (‘c’) 아닌지 (‘n’)를 지정하는 문자열이고 생략하면 ‘c’가 기본적으로 선택된다. (‘p’는 프로파일링 기능을 넣은 컴파일 옵션임) 컴파일을 하는 것이 훨씬 더 실행 효율이 높으므로 보통은 기본 옵션으로 생성하면 문제가 없을 것이다.

파일에 저장된 함수

 함수를 파일에서 정의할 수 있으며 Scilab 함수 파일의 확장자는 .sci 으로 정해져 있다.( 다른 확장자도 사용할 수는 있다.) Scilab 의 sci파일에는 여러 개의 함수가 정의될 수 있으며 파일명과 함수명은 크게 상관이 없어서 서로 달라도 된다. 그리고 외부에서 각각의 함수를 개별적으로 호출할 수 있다. (MATALB은 파일명과 첫 함수명이 같아야 하고 첫 번째 함수를 제외하고 다른 함수들은 외부에서 호출할 수는 없다.)


 파일에 저장된 함수를 사용하기 위해서 컴파일/로드 되어야 한다. 이것을 수행하는 함수는 exec()함수이며 이 함수는 스크립트파일을 실행할 때뿐만 아니라 함수를 컴파일하고 로드하는데에도 사용된다. (인라인 함수를 정의하는 deff()함수도 컴파일을 자동으로 수행한다.)


>> exec(‘filename’ [,mode])


만약 함수 파일이 현재 디렉토리에 있다면 파일명만 써도 되는데 그렇지 않다면 파일명을 포함한 전체경로를 첫 번째 인자로 써주어야 한다. 두 번째 인자는 실행모드로서 선택사항이다. 옵션으로 주는 mode값과 해당하는 동작은 다음과 같다.


[표 1] exec()함수의 mode 옵션

mode 값

동작

0

초기값. 세미콜론(;)이 붙지 않은 명령의 결과만 콘솔창에 출력.

-1

아무런 출력도 하지 않음.

1

(마치 직접 콘솔창에 입력하듯이) 한 줄씩 명령과 그 결과를 출력.

2

프롬프트(-->>) 표시 ??? (0번과 거의 유사함)

3

각 명령 줄과 프롬프트 표시. (2번과 거의 유사함)

4

???

7

한 줄씩 실행 후 멈춤. 엔터키 입력으로 실행 (데모를 보일 때 유용함)


exec()함수로 읽어들인 사용자 함수는 workspace에 컴파일되서 올라오므로 바로 사용가능하다.



Posted by 살레시오

댓글을 달아 주세요

  1. shh 2018.04.04 15:09  댓글주소  수정/삭제  댓글쓰기

    감사합니다. 잘배우고 갑니다.

 C++ 에서 함수를 호출하는데 있어서는 어느 정도 댓가가 따른다. 함수를 호출하기 직전에 기존 정보를 저장하고 인자를 넘겨주고 실행 순서를 바꾼 후 함수의 수행이 끝나면 사용한 메모리를 정리하고 반환값을 받는다. 즉 함수 호출 전후에 필수적으로 수행해야하고 메모리와 시간을 요하는 작업들이 있는 것이다. PC에서 수행되는 프로그램을 작성할 때에는 이러한 오버헤드는 무시할 수 있을 것이다. 하지만 아두이노와 같은 메모리나 성능이 매우 제약된 프로세서를 프로그래밍할 경우에는 무시 못할 성능 저하 요인이 될 수도 있다.


 C++의 인라인(inline)함수는 함수의 길이가 매우 짧을 경우에 효율을 높이기 위해서 도입된 방법으로서 함수의 선언부 앞에 inline 이라는 키워드로 구현된다. 이전의  코드로 예를 들면 다음과 같다.

inline boolean Button::isPushed() {
   return (digitalRead(_pin) == LOW)? true:false;
}


컴파일러는 인라인 함수를 호출하는 곳에 인라인 함수의 코드를 그대로 삽입하여 함수의 호출이 일어나지 않도록 한다. 이렇게 되면 함수를 호출할 때 드는 비용이 없어지기 때문에 속도가 더 올라간다. 반대 급부로 프로그램의 길이는 더 길어지게 된다.

 다른 객체지향 언어(JAVA, C# 등등)도 마찬가지지만 C++도 비교적 작은 크기의 함수를 많이 사용한다. 대표적인 것이 멤버 변수를 접근하는 getter/setter 함수인데 이러한 사용 빈도가 높고 크기가 작은 함수들을 inline으로 정의해 놓으면 더 높은 실행 효율을 얻을 수 있다.


 함수를 inline으로 설정했다고 모두 코드를 치환하는 것은 아니고 컴파일러에 따라서 동작 방식이 다르다. 자기 자신을 호출하는 재귀함수나 반복문, switch문 등이 포함된 함수는 inline으로 지정했다고 하더라도 컴파일러에 의해서 인라인 선언이 무시될 수도 있다. 또한 생성자를 포함하여 모든 멤버 함수가 인라인으로 선언될 수 있다. 이전 포스트의 Button클래스의 멤버 함수를 인라인 함수로 지정하면 다음과 같다.

class Button {
   public:
     Button(byte, boolean); // 생성자
     boolean isPushed(); // 버튼이 눌렸다면 true를 반환하는 멤버 함수
   private:
     byte _pin; // 연결된 핀
     boolean _internalPullup; //내부에 풀업이 되었는가
};
// 생성자의 구현
inline Button::Button(byte pin, boolean internalPullUp = true) {
   _pin = pin;
   _internalPullup = internalPullUp;
   if (_internalPullup)
       pinMode(_pin, INPUT_PULLUP);
   else
   pinMode(_pin, INPUT);
}
// 멤버 함수의 구현
inline boolean Button::isPushed() {
   return (digitalRead(_pin) == LOW)? true:false;
}

 멤버 함수의 크기가 작을 경우 클래스의 선언부에 바로 함수를 구현해도 무방하다. 즉, 위 예의 isPushed() 함수를 다음과 같이 클래스의 선언부에 바로 구현해도 된다.

class Button {
   public:
     Button(byte, boolean); // 생성자
     boolean isPushed();{
       return (digitalRead(_pin) == LOW)? true:false;
     }
     boolean isPushed(); // 버튼이 눌렸다면 true를 반환하는 멤버 함수
   private:
     byte _pin; // 연결된 핀
     boolean _internalPullup; //내부에 풀업이 되었는가
};
// 생성자의 구현
inline Button::Button(byte pin, boolean internalPullUp = true) {
   _pin = pin;
   _internalPullup = internalPullUp;
   if (_internalPullup)
       pinMode(_pin, INPUT_PULLUP);
   else
       pinMode(_pin, INPUT);
}

 단 한 가지 주의할 점은 컴파일러는 클래스 선언부에 바로 구현된 멤버 함수들에 대해서는 inline선언이 없어도 인라인 함수로 자동으로 처리한다. 따라서 이 예에서 isPushed()함수는 인라인 함수로 자동으로 간주된다.



Posted by 살레시오

댓글을 달아 주세요