Nanashi-softプログラマ専用Windows gcc SDL


◇Windowsでgcc+SDL -分割コンパイルするソースの書き方-

1つのソースファイルに全部書いても構わないのですが
ヒープメモリの関係上、プログラム記述しているデータなどは別ファイルにしたい事もあります
プログラムを分割する方法を説明します

○元のソース

例えば以下のようなソースがあるとします
・test.cの中身

#include "testsrc1.h"
int main(int argc,char *argv[]){
  int i;
  int len;

  len= sizeof(bmp);
  bmpto= (unsigned char *)malloc(len);

  half(bmpto, len);

  printf("%s\n", FILENAME);
  for(i=0; i < len; i++){
    printf("%d\n", bmpto[i]);
  }

  free(bmpto);
}

void half(unsigned char *inbmp, int len){
  int i;
  for(i=0; i < len; i++){
    bmpto[i]= bmp[i] >> 1;
  }
}

・testsrc1.hの中身

#define FILENAME "test.bmp"

unsigned char *bmpto;

const unsigned char bmp[]={
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
};

void half(unsigned char *,int);


これを実行しようとしたらメモリ不足になったとします
そこで、bmpデータを別ソースにする事にしました

○ソースを分割する

単純にbmpデータ部分のみを別ファイルにしたとします

・testsrc2.cの中身

const unsigned char bmp[]={
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
};

testsrc1.hの中からbmpソースを削除します

この状態でビルドしようとすると、

$ gcc `sdl-config --cflags` -c testsrc1.c
testsrc1.c: In function `SDL_main':
testsrc1.c:6: error: `bmp' undeclared (first use in this function)
testsrc1.c:6: error: (Each undeclared identifier is reported only once
testsrc1.c:6: error: for each function it appears in.)
testsrc1.c: In function `half':
testsrc1.c:22: error: `bmp' undeclared (first use in this function)
make: *** [testsrc1.o] Error 1

bmp変数が宣言されていないエラーが出ます

これを認識させる為には、externを宣言します
externは「中身は他で宣言済みですよ」と言う意味だと覚えておけば良いでしょう

testsrc1.hに

extern unsigned char bmp[];

を記述します

○extern(エクスターン)宣言の罠

この状態でビルドしようとすると、

$ gcc `sdl-config --cflags` -c testsrc1.c
testsrc1.c: In function `SDL_main':
testsrc1.c:6: error: invalid application of `sizeof' to incomplete type `({anonymous})'
make: *** [testsrc1.o] Error 1

sizeofが実行できないエラーがでます
externで宣言した変数にはsizeofが実行できません(そう思っておいた方がバグがでません)

ここで理解できる人だけ覚えておくと良い事を1つ
externは『宣言』ですので sizeofが使えないのは当たり前です
『宣言』は中身が無いもの、それに対して『定義』は中身が出来るものです
ですから、私は『extern宣言』と『宣言』の部分まで1くくりで覚えています
『定義』 → const unsigned char bmp[]={〜
『宣言』 → extern unsigned char bmp[];

仕方が無いので、testsrc2.cにサイズを返す関数を定義します

int bmpsize(){
	return sizeof(bmp);
}

それを、testsrc1.cから呼び出します

  len= bmpsize(bmp);


これでビルドできるようになりました

$ gcc `sdl-config --cflags` -c testsrc1.c
$ gcc `sdl-config --cflags` -c testsrc2.c
$ gcc -o test testsrc1.o testsrc2.o `sdl-config --libs`

○分割後ソース

・testsrc1.c

#include "testsrc1.h"
int main(int argc,char *argv[]){
  int i;
  int len;

  len= bmpsize(bmp);
  bmpto= (unsigned char *)malloc(len);

  half(bmpto, len);

  printf("%s\n", FILENAME);
  for(i=0; i < len; i++){
    printf("%d\n", bmpto[i]);
  }

  free(bmpto);
}

void half(unsigned char *inbmp, int len){
  int i;
  for(i=0; i < len; i++){
    bmpto[i]= bmp[i] >> 1;
  }
}


・testsrc1.h

#define FILENAME "test.bmp"

unsigned char *bmpto;

extern const unsigned char bmp[];

void half(unsigned char *,int);


・testsrc2.c

const unsigned char bmp[]={
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
};

int bmpsize(){
	return sizeof(bmp);
}



TOPプログラマ専用Windows gcc SDL