Archiv verlassen und diese Seite im Standarddesign anzeigen : dynamischer Speicher für gtk buttons mit ansiC
Hallo allerseits!
Ich möchte einer Matix von gtk_widget dynamisch Speicher zuweisen.
Bisher habe ich eine globaldefinierte Matrix:
static GtkWidget *(button[DIM][DIM]);
Diese möchte ich nun dynamisch machen. Am besten analog zu meinem Beispiel für eine Integer-Matrix. aus der globalen Matrix
matrix[DIM][DIM]
ist folgendes geworden:
int **malloc_2D(size_t y, size_t x){
int **array_2d;
int *p;
size_t row;
printf("Anzahl der angeforderten Speicherzellen: %d\n",(x*y*sizeof(**array_2d)+y*sizeof(**array_2d)));
array_2d=(int **)realloc(matrix, x*y*sizeof(**array_2d)+y*sizeof(**array_2d));
if(array_2d == NULL){
printf("Speicheranforderung fehlgeschlagen\n");
return NULL;}
else{
for(row=0, p=(int *)array_2d+y; row<y; row++, p+=x){
array_2d[row]=p;}}
return array_2d;}
Florian
peschmae
15-03-2003, 10:27
das Problem ist, dass wir hier keinen wirklichen Gtk - Experten haben...
anda_skoa ist unbestritten für QT (und auch sonst ziemlich alles ;-)) zuständig
um Java kümmern sich diverse Leute (ich auch)
aber Gtk - Guru haben wir hier leider keinen...
MfG Peschmä
anda_skoa
15-03-2003, 11:23
Original geschrieben von peschmae
das Problem ist, dass wir hier keinen wirklichen Gtk - Experten haben...
tkortkamp ist GTK+ Entwickler, wenn ich das richtig in Erinnerung habe.
Außerdem ist das mehr ein C Problem, darum lasse ich es auch in diesem Forum.
@Florian:
geht es nicht, wenn du statt int GtkWidget schreibst?
Ciao,
_
Ich habe verschiedene Varianten ausprobiert, in denen ich "int" durch "GtkWidget *" ausgetauscht habe. Es gab dabei auch Varianten, bei denen der Compiler keine Warnings ausgespuckt hat. Leider endete bisher alles in einem Segmentation Fault. Aber vielleicht gibt es hier ja einen Pointer-Crack?
Seh' ich das jetzt richtig? Du willst eine Matrix haben, in der die Elemente Pointer auf GtkWidgets sind. Wenn da so ist können wir das ja mal auskaspern.
Ich hab mal was mit ints probiert:
#include <stdio.h>
#include <unistd.h>
#include <malloc.h>
const int dimx = 10;
const int dimy = 10;
int **matrix;
int main (void)
{
int x, y, z;
matrix = (int**)malloc(dimx*dimy*sizeof(int*));
if (!matrix){
fprintf(stderr,"nicht genug speicher\n");
return 1;
}else fprintf(stderr,"speicher allokiert\n");
/* jetzt jedem matrixelement speicher zuordnen */
for (x = 0; x < dimx; x++)
for (y = 0; y < dimy; y++)
matrix[y*dimx + x] = (int*)malloc(sizeof(int));
/* matrix füllen */
z = 0;
for (x = 0; x < dimx; x++)
for (y = 0; y < dimy; y++)
*(matrix[y*dimx + x]) = ++z;
/* ausgeben */
for (x = 0; x < dimx; x++){
for (y = 0; y < dimy; y++)
printf("%d ", *(matrix[y*dimx + x]));
printf("\n");
}
/* speicher freigeben */
for (x = 0; x < dimx; x++)
for (y = 0; y < dimy; y++)
free(matrix[y*dimx + x]);
free(matrix);
printf("fertig\n");
return 0;
}
...und nun mit einer echten 2d-matrix:
const int dimx = 10;
const int dimy = 10;
int ***matrix;
int main (void)
{
int x, y, z;
matrix = (int***)malloc(dimx*sizeof(int*));
for (x = 0; x < dimx; x++)
matrix[x] = (int**)malloc(dimy*sizeof(int*));
fprintf(stderr,"speicher allokiert\n");
/* jetzt jedem matrixelement speicher zuordnen */
for (x = 0; x < dimx; x++)
for (y = 0; y < dimy; y++)
matrix[y][x] = (int*)malloc(sizeof(int));
/* matrix füllen */
z = 0;
for (x = 0; x < dimx; x++)
for (y = 0; y < dimy; y++)
*(matrix[y][x]) = ++z;
/* ausgeben */
for (x = 0; x < dimx; x++){
for (y = 0; y < dimy; y++)
printf("%d ", *(matrix[y][x]));
printf("\n");
}
/* speicher freigeben */
for (x = 0; x < dimx; x++)
for (y = 0; y < dimy; y++)
free(matrix[y][x]);
for (x = 0; x < dimx; x++)
free(matrix[x]);
free(matrix);
printf("fertig\n");
return 0;
}
@brotzi: vielen Dank für die Mühe. Ich habe vorhin noch ein wenig rumgebastelt und bin doch noch auf eine Lösung gekommen. Leider ging dann das Internet nicht, so dass ich sie erst jetzt posten kann.
@all:
static GtkWidget ***button;
GtkWidget ***gtk_malloc_2D(size_t y, size_t x){
int **array_2d;
int *p;
size_t row;
printf("Anzahl der angeforderten Speicherzellen: %d\n",(x*y*sizeof(GtkWidget)+y*sizeof(**array_2d)));
array_2d=(int **)realloc(buttons, x*y*sizeof(GtkWidget)+y*sizeof(**array_2d));
if(array_2d == NULL){
printf("Speicheranforderung fehlgeschlagen\n");
return NULL;}
else{
for(row=0, p=(int *)array_2d+y; row<y; row++, p+=x*12){
array_2d[row]=p;}}
return GINT_TO_POINTER(array_2d);}
Ich bevorzuge diese Lösung (abgeguckt von http://www.pronix.de und hoffendlich berichtigt), weil nur einmal Speicher alloziert wird (schnellerer Code) und man trotzdem auf den Inhalt der Matrixelemente mit matrix[y][x] bzw. mit button[y][x] zugreifen kann. Auch wenn der Code etwas kryptisch ist und ich mich dafür vielleicht nochmal verfluchen werde.Falls jemand Fehler findet oder Anregungen hat, bitte posten.
Florian
Wäre alles prima, wenn Ihr endlich damit aufhören würdet den Rückgabewert von malloc zu casten!
Ein void* ist ein universal Pointer!
den return wert von malloc casten ist zB hier toedlich:
#include <stdio.h>
#include <string.h>
int main(void)
{
char* buffer=(char*)malloc(20);
strcpy(buffer,"Hallo Welt!");
printf("%s",buffer);
free(buffer);
return 0;
}
Tatsächlich gibt's nur auf den Maschinen einen Fehler, deren interne Repräsentation eines 'int'-Wertes von der eines Pointers abweicht.
In C89 hat aber jede Funktion, die keine Deklaration und keinen Prototyp hat automatisch den Rückgabewert 'int'. Wenn nun ein void* fehlerfrei in einen int und zurück umgewandelt werden kann, ist das ein Problem. Auf 'normalen' Rechnern hat man das Problem (leider) nicht, darum wird dieser Fehler oft gemacht.
GreetZ
ReSeT
anda_skoa
16-03-2003, 12:53
Original geschrieben von ReSeT
Tatsächlich gibt's nur auf den Maschinen einen Fehler, deren interne Repräsentation eines 'int'-Wertes von der eines Pointers abweicht.
Was zum Beispiel auf allen 64 Bit Plattformen der Fall ist, da dort ein Pointer 64 Bit lang ist, ein int normalerweise aber wie auf 32 Bit Plattformen nur 32 Bit.
Kommt auch oft vor, das Leute long Werte auf int zuweisen, weil auf 32 Bit Plattformen zufällig long gleichlang ist wie int.
Auf 64 Bit Plttformen ist das überlicherweise nämlich auch 64 Bit
Ciao,
_
Ist ja toll, dass Ihr Euch so gut auskennt!
Ich kenne mich nicht so gut aus. Für mich wäre an dieser Stelle viel hilfreicher gewesen, wie man es richtig macht. Das TÖTLICHE Beispiel sagt mir zwar, dass ich das wohl nicht sicher auf anderen Plattformen laufen lassen kann, hilft aber irgendwie nicht weiter.
Wenn jemand eine plattformunabhängige Variante meiner Funktion posten könnte und mir nicht nur zwischen den Zeilen mitteilt: "Du hast ja wohl überhaupt keine Ahnung", wäre ich sehr erfreut.
Florian
@ReSeT: was soll der Quatsch? Ein char* ist genauso groß wie ein int* oder ein void* auf allen Systemen! Wenn man ein malloc macht wird lediglich die angegebene Anzahl bytes allokiert und die Adresse zurückgegeben. Unabhängig von Endianess oder sonstwas! Falsch wäre es natürlich aus einem char* ein int* zu casten wenn man nicht auf die Endianess achtet.
Größen von int usw. haben wir beide übrigens mit sizeof() beachtet, sodaß der cast erlaubt ist!
@Brotzi: Ich weise hier nur auf Unnötigkeiten hin, die man schlichtweg weglassen kann, ich habe mich über dieses Problem schon mehrfach in Foren rumgestritten und werde es hier nicht wieder tun.
Tatsächlich gibt's nur auf den Maschinen einen Fehler, deren interne Repräsentation eines 'int'-Wertes von der eines Pointers abweicht.
@Florian: Lass einfach den Cast weg und binde die stdlib.h ein, dann ist alles gut.
und mir nicht nur zwischen den Zeilen mitteilt: "Du hast ja wohl überhaupt keine Ahnung",
Wenn Du das so verstanden hast, es war jedenfalls nicht meine Absicht, das so rüberkommen zu lassen.
GreetZ
ReSeT
Ähm...
Auf das komische Casten bin ich ja erst gekommen, weil ich sonst die folgende Fehlermeldung erhalte:
gcc `gtk-config --libs --cflags` -Wall -pedantic -ansi gtk_puzzle-0.8.c -o gtk_puzzle
gtk_puzzle-0.9.c: In function `gtk_malloc_2D':
gtk_puzzle-0.9.c:38: warning: return from incompatible pointer type
38: return array_2d;}
Wie gehts denn nun????????
Florian
(stdlib.h ist übrigens eingebunden)
anda_skoa
18-03-2003, 14:17
p und array_2d sind noch int anstatt GtkWidget
Ciao,
_
Also der code sieht jetzt so aus:
GtkWidget ***gtk_malloc_2D(size_t y, size_t x){
GtkWidget **array_2d;
GtkWidget *p;
size_t row;
printf("Anzahl der angeforderten Speicherzellen: %d\n",(x*y*sizeof(GtkWidget)+y*sizeof(**array_2d)));
array_2d=(GtkWidget **)realloc(buttons, x*y*sizeof(GtkWidget)+y*sizeof(**array_2d));
if(array_2d == NULL){
printf("Speicheranforderung fehlgeschlagen\n");
return NULL;}
else{
for(row=0, p=(GtkWidget *)array_2d+y; row<y; row++, p+=x*12){
array_2d[row]=p;}}
return array_2d;}
Fehlermeldung s.o.
anda_skoa
18-03-2003, 15:07
Vergleich mal dein beiden Werte:
GtkWidget *** // Typ des Returnwert der Funktione
und
GtkWidget ** // Typ von array_2d
Ciao,
_
Ich hab (hoffentlich) die LÖSUNG! Nach einigen weiteren Segmentation Faults hat das hier geklappt. *freu*
GtkWidget ***gtk_malloc_2D(size_t y, size_t x){
GtkWidget ***array_2d;
GtkWidget **p;
size_t row;
printf("Anzahl der angeforderten Speicherzellen: %d\n",(x*y*sizeof(GtkWidget)+y*sizeof(***array_2d)));
array_2d=(GtkWidget ***)realloc(buttons, x*y*sizeof(GtkWidget)+y*sizeof(***array_2d));
if(array_2d == NULL){
printf("Speicheranforderung fehlgeschlagen\n");
return NULL;}
else{
for(row=0, p=(GtkWidget **)array_2d+y; row<y; row++, p+=x*12){
array_2d[row]=p;}}
return array_2d;}
Ja, ja, ich weiss: "So schwer wars doch gar nicht". Aber diese ganzen Sternchen können schon verwirren.
Auf jeden Fall vielen Dank für Eure Hilfe!
@reset: auch zufrieden?
Florian
Powered by vBulletin® Version 4.2.5 Copyright ©2025 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.