・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;
}