posted by cimple 2010. 8. 28. 04:35

프로그래밍을 하다 보면 황당한 경우를 만날 때가 있다. 그 중에 가장 당황스러울 때가, 헤더 파일들을 include 할 때, 특정 순서에 따라서 오류가 나고 안 나고가 결정될 때가 있을 때이다. 다시 말해서

#include <headerfileA.h>
#include <headerfileB.h>

이렇게 include 하면 문제가 없는데,

#include <headerfileB.h>
#include <headerfileA.h>


이렇게 include 하면 문제가 생기는 경우 말이다.

사실 이러한 경우가 발생하는 문제는 상당히 다양하다. 헤더 파일이 헤더 파일을 서로 서로 include 하는 좀 난잡한 구조로 코딩을 한다면 이런 문제가 발생할 가능성이 높다. 때문에 능력있는 프로그래머라면 각 헤더 파일이 의미하는 바와, 그 관계를 잘 설정해 놓고 코딩해야 할 것이다.

하지만 굉장히 난감한 경우도 있는데, 외부 라이브러리를 사용했을 때이다. 외부 라이브러리를 include 했는데 특정 순서에 따라서 컴파일이 되고 안 되고 한다면 정말 해결하기 어려운 노릇이다.

그 중에서 이번에 OpenMesh 를 활용한 Maya 프로그래밍을 하면서 겪었던 일.





#include <OpenMesh/Core/System/config.hh>
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/PolyMeshT.hh>
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/Mesh/Traits.hh>
#include <OpenMesh/Core/Mesh/Attributes.hh>

#include <maya/MPxNode.h>
#include <maya/MTypeId.h>




Maya Node 를 만들 때 헤더 파일에 위와 같이 라이브러리 헤더 파일들을 include 했더니, 무수한 에러가 발생하였다.

그래서 OpenMesh 관련 헤더파일들을 cpp 파일에서 include 했더니, 에러는 사라졌다. 하지만, 노드 헤더 파일에서 노드 클래스를 구성할 때, OpenMesh 의 객체를 사용해야 하므로 무조건 노드 헤더파일 안에서 OpenMesh 관련 헤더파일들을 include 해야 하는 상황이었다.


빼도 박도 도망가도 못하는 상황이었는데 수백개씩 뜨는 에러메시지 중 다음과 같은 메시지가 눈에 띄었다.




1>c:\program files\openmesh-2.0-rc3\openmesh-2.0-rc3\src\openmesh\core\geometry\vectort_inc.hh(430) : warning C4003: 'max' 매크로의 실제 매개 변수가 부족합니다.
1>c:\program files\openmesh-2.0-rc3\openmesh-2.0-rc3\src\openmesh\core\geometry\vectort_inc.hh(438) : warning C4003: 'min' 매크로의 실제 매개 변수가 부족합니다.
1>c:\program files\openmesh-2.0-rc3\openmesh-2.0-rc3\src\openmesh\core\geometry\vectort_inc.hh(469) : warning C4003: 'min' 매크로의 실제 매개 변수가 부족합니다.
1>c:\program files\openmesh-2.0-rc3\openmesh-2.0-rc3\src\openmesh\core\geometry\vectort_inc.hh(474) : warning C4003: 'max' 매크로의 실제 매개 변수가 부족합니다.
.
.
.


무언가 min, max 를 OpenMesh 에서 사용하는데, 이것이 충돌을 일으키는 것 같았다. 그래서 구글을 좀 뒤져서, 다음과 같은 좋은 정보들을 찾았다.


include 순서 오류에 대한 질문/답변글

min/max 매크로로 인한 오류 해결 방법


즉, Miscrosoft 가 min, max 같은 단어들을 '매크로' 로 등록해 둔 것이 문제라는 것이다. 사실 짧은 프로그래밍 경력과 실력으로 그 의미와 문제점을 명확히 알아듣기가 어렵다.

해결책은 위의 링크에도 소개되었듯이 다음과 같이 헤더파일 상단에 삽입하면 된다.



#define NOMINMAX
#ifdef max
 #undef max
#endif
#ifdef min
 #undef min
#endif




...하나 하나 알아가는게 쉽지만은 않다.


ThEnd.
posted by cimple 2010. 8. 13. 14:08

C 로부터 시작해서 C++ 로 파일 입출력을 수행하는 방법은 여러 가지가 있다.

하지만 이번 포스팅에서는 이번에 Maya Programming 을 하면서 내가 직접 수행했던 파일 입출력을 정리해두고자 한다.



일단 기본적으로 C++ 에서 파일 입출력을 위해서 include 해야 할 파일은

#include <fstream>

이다.

그런데 마야 프로그래밍을 할 때에 이런 식으로 기본 C++ 파일 입출력을 수행하면 코드 내에서 명령어를 찾을 수 없다는 메시지가 계속해서 뜬다. ㅡ_ㅡ;;;

(namespace 만 제대로 처리해주면 위의 문제(?) 를 해결할 수 있습니다.
std::ifstream  fin;
이런 식으로 사용해주면 된다는 것이지요.
아니면 만사형통 using namespace std; 를 써도 되지만 물론 비추이지요.)


마야 프로그래밍에서 파일 입출력을 하기 위해서는

#include <maya/MFStream.h>

를 include 해서 사용하도록 한다.

처음에 include 하는 부분만 다르지, 객체를 생성해서 파일 입출력을 수행하는 코드 부분은 같다.



1. 파일 출력

파일을 출력하는 방법은 간단하다. 다음의 과정을 거치면 된다.

1. 파일을 출력하기 위한 ofstream 객체를 만든다.
2. 파일을 연다.
3. 파일에 쓴다.
4. 파일을 닫는다.


예제는 다음과 같다.

ofstream fout;
fout.open("filename.dat");
fout << "Hello, World!" << endl;
fout.close();

객체를 만들 때 바로 파일에 연결해도 된다.

ofstream fout("filename.dat");





2. 파일 입력

파일을 입력하기 위해서는 다음의 과정을 거치면 된다.

1. 파일을 입력받기 위한 ifstream 객체를 만든다.
2. 파일을 연다.
3. 파일을 읽는다.
4. 파일을 닫는다.


예제는 다음과 같다.

ifstream fin;
fin.open("filename.dat");
int variable;
fin >> variable;
fin.close();


이 때, ifstream 으로 파일을 한 번 읽으면 파일에 공백으로 띄워져 있는 데이터 하나를 읽게 된다.
예를 들어 파일이

15   4   9   6
7    3   5   4

대충 이런 식으로 되어 있다면, fin 을 한 번 하면 15를 variable 에 저장한다.
파일을 처음부터 끝까지 읽고 싶다면 while 문을 사용하면 된다.
fstream 에서는 파일의 끝일 경우 함수가 0을 리턴하므로 파일의 끝까지 입력받을 수 있다.

int sum_variable;
while( fin>> variable)
{
sum_variable += variable;
}

이런 식으로 간단하게 사용할 수 있다.






3. 파일 입/출력시 파일의 경로 문제

파일을 입/출력받을 때 파일의 경로가 어디에 있는가는 좀 복잡하면서도 까다로운 문제이다.

아마도 절대경로 / 상대경로 등으로 파일의 입력 위치를 지정해 줄 수도 있을 것이다.




그런데 작업을 하면서 한가지 의아한 상황이 발생했는데

파일을 출력할 때에 처음에는 Visual Studio project  폴더의 debug 폴더 안으로 파일이 출력되다가,

갑자기 MAYA scene 파일이 있는 곳에 파일이 출력되는 것이다;


파일을 입력할 때도 마찬가지로

Visual Studio project 폴더 안에 넣어 놓으면 파일을 찾지 못하고,

MAYA scene 파일 안에 있어야 파일을 입력받았다.

Visual Studio 의 링크설정 등에는 분명히 output 경로를 debug 폴더 안으로 출력하도록 되어 있을 텐데, 이건 좀 요상한 일.





4. 여러 개의 파일 입력

여러 개의 파일 입력을 받는 과정에서 약간의 문제가 생겼다.

ifstream 객체 fin 을 하나 만들어서 받고 -> close -> 다시 받고

하면 될 줄 알았는데, 처음에는 받아지는데 다음에 받지 못하는 경우가 생겼다.

이러한 경우가 생겼을 때 .clear() 함수를 통해서 해결할 수 있었다.

즉,

std::ifstream fin;
fin.open("a.txt");
fin.close();
fin.clear();
fin.open("b.txt");
fin.close();

이런 식으로 해야 a.txt 읽고 -> b.txt 읽고, 이런 식으로 작업이 가능하다.




5. 파일을 line 단위로 입력

파일을 line 단위로 입력받아야 할 때가 있는데, 파일 전체의 길이가 너무 길 때이다.

2번처럼 파일의 처음부터 끝까지 한번에 입력받을 경우, 파일의 길이가 너무 길면 vector 같은 저장 공간에 한번에 저장할 수가 없게 된다.

때문에 line 별로 입력받아야 할 필요가 생기는데, 코드는 다음과 같다.






ThEnd.