C: Разыменование указателя на неполный тип ошибки - PullRequest
1 голос
/ 16 октября 2011

Проект, который я пытаюсь скомпилировать в OS X: https://github.com/Ramblurr/PietCreator

К сожалению, не могу исправить проблемы со следующими строками:

width = info_ptr->width;
height = info_ptr->height;
ncol = 2 << (info_ptr->bit_depth - 1);

, которые приводят к ошибкам:

file.c: In function ‘read_png’:
file.c:1117: error: dereferencing pointer to incomplete type
file.c:1118: error: dereferencing pointer to incomplete type
file.c:1119: error: dereferencing pointer to incomplete type

Полный код функции read_png ниже:

#include <png.h>
#include <math.h>

png_byte bit_depth;

png_structp png_ptr;
png_infop info_ptr;
int number_of_passes;
png_bytep * row_pointers;


int
read_png (char *fname)
{
  char header [8];

  FILE *in;
  int i, j, ncol, rc;

  if (! strcmp (fname, "-")) {
    /* read from stdin: */
    vprintf ("info: not trying to read png from stdin\n");
    return -1;
  }

  if (! (in = fopen (fname, "rb"))) { 
    fprintf (stderr, "cannot open `%s'; reason: %s\n", fname,
         strerror (errno));
    return -1;
  }

  if (! in || (rc = fread (header, 1, 8, in)) != 8
      || png_sig_cmp ((unsigned char *) header, 0, 8) != 0) {
    return -1;
  }

  if (! (png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0))
      || ! (info_ptr = png_create_info_struct (png_ptr))) {
    return -1;
  }

  png_init_io (png_ptr, in);
  png_set_sig_bytes (png_ptr, 8);

  png_read_png (png_ptr, info_ptr, 
        PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_STRIP_ALPHA
        | PNG_TRANSFORM_EXPAND, NULL);
  /**       | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_SHIFT **/

  row_pointers = png_get_rows (png_ptr, info_ptr);

  width = info_ptr->width;
  height = info_ptr->height;
  ncol = 2 << (info_ptr->bit_depth - 1);

  vprintf ("info: got %d x %d pixel with %d cols\n", width, height, ncol);

  alloc_cells (width, height);

  for (j = 0; j < height; j++) {
    png_byte *row = row_pointers [j];
    for (i = 0; i < width; i++) {

      png_byte *ptr = & row [i * 3];

      /* ncol always 256 ? */
      int r = (ptr [0] * 256) / ncol;
      int g = (ptr [1] * 256) / ncol;
      int b = (ptr [2] * 256) / ncol;

      int col = ((r * 256 + g) * 256) + b;
      int col_idx = get_color_idx (col);

      if (col_idx < 0) {
    if (unknown_color == -1) {
      fprintf (stderr, "cannot read from `%s'; reason: invalid color found\n",
           fname);
      return -1;
    } else {
      /* set to black or white: */
      col_idx = (unknown_color == 0 ? c_black : c_white);
    }
      }

      set_cell (i, j, col_idx);
    }
  }

  return 0;
}

Ответы [ 5 ]

4 голосов
/ 17 октября 2011

Я думаю, что это по замыслу создателя модуля png.h.

Должно быть, png_infop объявлено как указатель на структуру в "png.h". Фактическое объявление и определение структуры должно быть в "png.c".

Автор не хочет раскрывать внутренности struct, поэтому struct определен в "png.c".

Это означает, что вы не можете получить доступ ни к какому члену структуры (например: info_ptr->width, info_ptr->height, info_ptr->bit_depth.

Члены struct не предназначены для доступа пользователя.

Могу поспорить, что есть функции для доступа к этим членам, если автор считает, что вам понадобится информация width, height или bit_depth (то есть: getWidth(info_ptr), getHeight(info_ptr), ...).

2 голосов
/ 16 октября 2011

Вам нужно заглянуть в png.h (или его документацию), выяснить, на что указывает тип png_infop, а затем выяснить, как вы должны получить доступ к его полям.Предполагая, что этот указатель действительно является правильным средством для получения этих данных, вам нужно либо включить определение этого типа (чтобы компилятор знал о своих членах данных width и т. Д.) Из какого-то другого заголовка, либоФункции получения, которые вы должны вызывать, которые принимают параметр png_infop и возвращают информацию, которую вы ищете.

[Редактировать: выглядит так, как будто вы должны использовать png_get_IHDR или png_get_image_widthи др.]

1 голос
/ 20 октября 2011

Я успешно скомпилировал проект в Mac OS X 10.6.8.

git clone https://github.com/Ramblurr/PietCreator.git   
cd PietCreator
mkdir build
cd build
cmake ../

-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Checking whether C compiler has -isysroot
-- Checking whether C compiler has -isysroot - yes
-- Checking whether C compiler supports OSX deployment target flag
-- Checking whether C compiler supports OSX deployment target flag - yes
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Checking whether CXX compiler has -isysroot
-- Checking whether CXX compiler has -isysroot - yes
-- Checking whether CXX compiler supports OSX deployment target flag
-- Checking whether CXX compiler supports OSX deployment target flag - yes
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Looking for Q_WS_X11
-- Looking for Q_WS_X11 - not found.
-- Looking for Q_WS_WIN
-- Looking for Q_WS_WIN - not found.
-- Looking for Q_WS_QWS
-- Looking for Q_WS_QWS - not found.
-- Looking for Q_WS_MAC
-- Looking for Q_WS_MAC - found
-- Looking for QT_MAC_USE_COCOA
-- Looking for QT_MAC_USE_COCOA - found
-- Found Qt-Version 4.7.4 (using /usr/local/bin/qmake)
-- Looking for gdImagePng in /usr/local/lib/libgd.dylib
-- Looking for gdImagePng in /usr/local/lib/libgd.dylib - found
-- Found ZLIB: /usr/include (found version "1.2.3")
-- Found PNG: /usr/X11R6/lib/libpng.dylib 
-- Looking for gdImageJpeg in /usr/local/lib/libgd.dylib
-- Looking for gdImageJpeg in /usr/local/lib/libgd.dylib - found
-- Found JPEG: /usr/local/lib/libjpeg.dylib 
-- Looking for gdImageGif in /usr/local/lib/libgd.dylib
-- Looking for gdImageGif in /usr/local/lib/libgd.dylib - found
-- Found GD: /usr/local/lib/libgd.dylib
-- Found GIF: /usr/local/lib/libgif.dylib 
-- Looking for include files HAVE_GD_H
-- Looking for include files HAVE_GD_H - found
-- Looking for include files HAVE_PNG_H
-- Looking for include files HAVE_PNG_H - not found.
-- Looking for include files HAVE_GIF_LIB_H
-- Looking for include files HAVE_GIF_LIB_H - found
-- Configuring done
-- Generating done
-- Build files have been written to: /Developer/workspace/png/PietCreator/build

После запуска make приложение было успешно скомпилировано:

Linking CXX executable pietcreator
[ 95%] Built target pietcreator
[ 97%] Generating NPietTest.moc
Scanning dependencies of target npiettest
[100%] Building CXX object npiet/CMakeFiles/npiettest.dir/test/NPietTest.cpp.o
Linking CXX executable npiettest
[100%] Built target npiettest

Единственные проблемы, которые я запускалВсе они были связаны с отсутствующими зависимостями при выполнении cmake ../.Мне пришлось скачать / скомпилировать / установить Qt 4.7.4 и Qt-mobility 1.2.0 .После этого мне также понадобились libgd и giflib , но затем я использовал brew для работы.

Я предлагаювы попробуйте другой git clone и попробуйте скомпилировать его заново.

Если вы хотите знать, brew установлен gd 2.0.36RC1 и giflib 4.1.6 .

0 голосов
/ 21 октября 2011

неполные ссылочные ошибки обычно возникают, когда у вас есть конструкция, как указано ниже:

struct foo;

int bar(void) {
     struct foo *p;
     p->a = 0;
}

здесь Структура foo объявлена, однако ее фактическое содержимое неизвестно, и приведет к разыменованию из-за ошибки неполного типа.

Философия этого заключается в том, чтобы принудительно использовать формальное API для манипулирования структурами данных.это гарантирует, что будущий API сможет намного легче изменить структуру, не затрагивая устаревшие программы.

Поэтому обычно заголовок API будет делать что-то вроде этого:

/*
 * foo.h part of foo API 
 */

struct foo;

extern void foo_set_a(struct foo *p, int value);
extern int foo_get_a(struct foo *p);

Он будет внутренне реализовывать API fooфункции ... например:

/* 
 * foo.c ... implements foo API 
 */

struct foo {
   int a;
};

void foo_set_a(struct foo *p, int value) {
    p->a = value;
}

int foo_get_a(struct foo *p) {
    return p->a;
}

и пользователь foo API может:

use_foo() {
    struct foo *my_foo;
    foo_set_a(my_foo, 1);
}
0 голосов
/ 16 октября 2011

Обычно вы получаете эту ошибку, когда у вас есть предварительная декларация в заголовке, и вы не включаете файл для соответствующего класса в исходный файл:

//header.h
class B;
class A{
A();
B* b;
}

//source.cpp
#include "header.h"
//include "B.h" //include header where B is defined to prevent error
A::A()
{
   b->foo(); //error, B is only a forward declaration
}

Поэтому вам необходимо включитьсоответствующий заголовок, предварительное объявление недостаточно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...