libpngとzlibをdll経由で使おうとするとエラーが起こる

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
なつやすみ

libpngとzlibをdll経由で使おうとするとエラーが起こる

#1

投稿記事 by なつやすみ » 3年前

hoge.dllというライブラリを作りたくて、libpngとzlibをダイナミックリンクして利用しようとしていますが、次のような現象が起きます。

・libpng16.dll と zlib.dllをリンクした場合
pngの読み込みの最中(png_read_imageを実行するとき)に
「ハンドルされない例外が ucrtbase.dll で発生しました」
というエラーが起こる。
リンクするライブラリをlibpng16_staticに変えて、png側をスタティックリンクにするとエラーは起きず関数は正常な返り値を返すようになりました。


再現手順:

zlibをビルドする(cmkae .. -G"Visual Studio 14 Win64" でvisual studioのプロジェクトを生成して64bit release ビルド)
libpngをビルドする(zlibと同様にvisual studioのプロジェクトを生成して64bit release ビルド)
hoge.dllのプロジェクトにそれぞれをダイナミックリンクして実行

環境:
visual studio2015(update3)

dllからdllを呼ぶ事自体は問題なさそうだと思ってるんですが、何か特殊な設定がいるのでしょうか?
以下に再現した時のソースコードを載せておきます。
よろしくお願い致します。

再現コード:

コード:

bool png::load(const char * file) {
	char header[8];
	FILE *fp = fopen(file, "rb");
	if( ! fp) {
		return false;
	}
	fread(header, 1, 8, fp);
	if(png_sig_cmp((png_const_bytep)header, 0, 8)) {
		fclose(fp);
		return false;
	}
	auto png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if( ! png_ptr) {
		fclose(fp);
		return false;
	}
	auto info_ptr = png_create_info_struct(png_ptr);
	if( ! info_ptr) {
	    png_destroy_read_struct(&png_ptr,NULL, NULL);
		fclose(fp);
		return false;
	}
	if(setjmp(png_jmpbuf(png_ptr))) {
	    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		fclose(fp);
		return false;
	}
	int bit_depth, color_type, interlace_type;
	u32 w = 0, h = 0;
	png_init_io(png_ptr, fp);
	png_set_sig_bytes(png_ptr, 8);
	png_read_info(png_ptr, info_ptr);
	png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, &interlace_type, NULL, NULL);
	raw_image::w = w;
	raw_image::h = h;
	if(color_type == PNG_COLOR_TYPE_RGBA) {
		raw_image::mode = rgba;
	}
	if (color_type == PNG_COLOR_TYPE_RGB) {
		raw_image::mode = rgb;
	}
	if (color_type == PNG_COLOR_TYPE_GRAY) {
		raw_image::mode = grayscale;
	}
	if (color_type == PNG_COLOR_TYPE_GA) {
		raw_image::mode = alpha_grayscale;
	}
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
	png_set_scale_16(png_ptr);
#else
	png_set_strip_16(png_ptr);
#endif
	png_set_strip_alpha(png_ptr);
	png_set_packing(png_ptr);
	png_set_packswap(png_ptr);
	if(color_type == PNG_COLOR_TYPE_PALETTE) {
		png_set_palette_to_rgb(png_ptr);
	}
	if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
		png_set_expand_gray_1_2_4_to_8(png_ptr);
	}
	if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) != 0) {
		png_set_tRNS_to_alpha(png_ptr);
	}
	png_color_16 my_background, *image_background;
	if(png_get_bKGD(png_ptr, info_ptr, &image_background) != 0) {
		png_set_background(png_ptr, image_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
	}
	else {
		png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
	}
	png_set_invert_mono(png_ptr);
	if(png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT) != 0){
		png_color_8p sig_bit_p;
		png_get_sBIT(png_ptr, info_ptr, &sig_bit_p);
		png_set_shift(png_ptr, sig_bit_p);
	}
	/*
	if((color_type & PNG_COLOR_MASK_COLOR) != 0) {
		png_set_bgr(png_ptr);
	}
	*/
	png_set_swap_alpha(png_ptr);
	png_set_swap(png_ptr);
	png_set_filler(png_ptr, 0xffff, PNG_FILLER_AFTER);
#ifdef PNG_READ_INTERLACING_SUPPORTED
	auto number_passes = png_set_interlace_handling(png_ptr);
#else
	number_passes = 1;
#endif
	png_read_update_info(png_ptr, info_ptr);
	if(setjmp(png_jmpbuf(png_ptr))) {
	    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		return false;
	}
	std::vector<png_bytep> pt;
	pt.resize(raw_image::h);
	raw_image::data.resize(png_get_rowbytes(png_ptr, info_ptr) * raw_image::h);
	u32 pos = 0;
	for(int i = 0; i < raw_image::h; ++i) {
		pt[i] = &raw_image::data[pos];
		pos += png_get_rowbytes(png_ptr, info_ptr);
	}
	png_read_image(png_ptr, (png_bytepp)&pt[0]);
	fclose(fp);
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	return true;
}

“C言語何でも質問掲示板” へ戻る