User Tools

Site Tools


blog:arduino_function_prototype_auto-generation_issues_with_struct_types

Arduino Function Prototype Auto-Generation Issues with Struct Types

아두이노 함수 프로토타입 자동 생성이 struct에서 오류를 일으키는 이유

개요 / Overview

Arduino IDE는 사용자가 .ino 파일에 작성한 코드를 그대로 컴파일하지 않는다. 대신 내부에서 여러 전처리 작업을 수행하는데, 그 중 “자동 함수 프로토타입 생성(auto function prototype generation)” 기능이 종종 C++의 타입 의존성 구조를 깨뜨려 오류를 발생시킨다.

특히 struct, enum, class 같은 사용자 정의 타입이 함수의 인자로 사용될 때 Arduino IDE가 순서를 잘못 판단하여 컴파일 에러가 발생하는 경우가 많다.

문제의 원인 (Root Cause)

Arduino IDE는 .ino 파일을 C++ 코드로 변환할 때 다음과 같은 작업을 수행한다:

  • 사용자 정의 함수에 대해 자동으로 함수 프로토타입을 생성
  • 이 프로토타입을 파일 상단에 삽입
  • 그 후에 C++ 컴파일러에게 전달

문제는 이러한 자동 생성된 프로토타입이 struct 정의보다 먼저 등장하는 경우가 있다는 것이다.

예:

bool checkLongPress(uint8_t pin, LongPressState &st, uint32_t nowMs); // 자동 생성됨
struct LongPressState {
    bool active;
    uint32_t startMs;
};

이 경우 컴파일러는 LongPressState가 선언되기 전에 사용되었다고 판단하여 오류를 발생시킨다.

왜 struct에서 특히 오류가 많은가

Arduino 프로토타입 생성기는 정규식 기반의 단순 파서이다. 다음과 같은 경우 구조체 타입 분석을 제대로 하지 못한다:

  • 사용자 정의 타입(struct, enum, class)이 함수 인자로 등장
  • struct 정의가 여러 줄
  • struct 바로 아래에 함수가 연달아 등장
  • 포인터(*), 참조(&) 포함
  • 여러 .ino 파일을 합칠 때 순서가 재배열

결과적으로 Arduino IDE는 타입 정의와 함수 선언의 실제 순서를 바꿔버리고, 그 때문에 “타입이 선언되지 않았다(has not been declared)” 오류가 발생한다.

Arduino 빌드 파이프라인

Arduino IDE는 내부에서 다음 순서로 파일을 재구성한다:

  • 여러 .ino 파일을 하나의 .cpp로 합침
  • #include <Arduino.h> 자동 삽입
  • 전역 함수에 대해 자동 프로토타입 생성 → 파일 상단에 추가
  • 이후 struct와 타입 정의 등장
  • 최종적으로 C++ 컴파일 진행

즉 사용자는 struct를 “위에 선언했다”고 생각하지만, IDE는 자동 프로토타입을 struct보다 앞에 두기 때문에 컴파일 에러가 난다.

대표적 오류 메시지

error: 'LongPressState' has not been declared

또는

invalid use of incomplete type 'LongPressState'

해결방법 (Solutions)

1. struct, enum, class를 반드시 .h/.cpp로 분리 (가장 추천)

예:

LongPress.h

#pragma once
struct LongPressState {
    bool active;
    uint32_t startMs;
};
bool checkLongPress(uint8_t pin, LongPressState &st, uint32_t nowMs);

LongPress.cpp

#include "LongPress.h"
bool checkLongPress(uint8_t pin, LongPressState &st, uint32_t nowMs) {
    ...
}

→ Arduino는 .h/.cpp 파일을 건드리지 않으므로 가장 안정적이다.

2. .ino 파일에 명시적 프로토타입 작성

struct LongPressState;
bool checkLongPress(uint8_t pin, LongPressState &st, uint32_t nowMs);

struct LongPressState {
    bool active;
    uint32_t startMs;
};

3. 사용자 함수들을 클래스 내부로 이동

Arduino는 클래스 내부 메서드에 대해 자동 프로토타입 생성을 하지 않는다.

권장 프로젝트 구조

/src
  LongPress.h
  LongPress.cpp
  Menu.h
  Menu.cpp
  PatternPlayer.h
  PatternPlayer.cpp
MainSketch.ino

요약

  • Arduino IDE는 .ino를 분석하여 자동 함수 프로토타입을 생성한다.
  • 이 자동 프로토타입이 struct 정의보다 앞에 와서 오류가 발생한다.
  • 이는 C++ 문제가 아니라 Arduino IDE 파서의 한계 때문이다.
  • 가장 좋은 해결책은 struct/enum/class를 .h/.cpp 파일로 분리하는 것이다.

저자 및 이용 안내

이 문서는 정해영의 아이디어와 지시에 따라 AI 도구(ChatGPT)의 도움을 받아 작성되었습니다.

본 문서는 Creative Commons CC0 1.0 Universal Public Domain Dedication에 따라 누구나 자유롭게 복제, 수정, 배포, 활용할 수 있으며, 출처 표시도 필요하지 않습니다. 다만, 내용의 정확성은 보장되지 않았으며, 정해영은 본 문서의 내용에 대해 어떠한 법적 책임도 지지 않습니다.

Authorship and Usage Notice

This document was written with the assistance of an AI tool (ChatGPT), based on the ideas and direction provided by Haeyoung Jeong.

It is released under the Creative Commons CC0 1.0 Universal Public Domain Dedication. Anyone may freely copy, modify, distribute, and use the content, with no requirement for attribution. However, the accuracy of the content is not guaranteed, and Haeyoung Jeong assumes no legal responsibility for its use.

blog/arduino_function_prototype_auto-generation_issues_with_struct_types.txt · Last modified: by hyjeong