/* Structure de Basic 3D qui peut-?tre partag?e pour les donn?es*/
typedef struct {
int B3DObjectAmount;
int *ObjectList;
int *LastCreatedObject;
}Basic3DStructType;
struct Basic3DStructType Basic3D;
typedef struct {
BOOL Exist;
int *PreviousObject;
int *NextObject;
int ID;
int Type;
float XPos, YPos, ZPos;
float XRot, YRot, ZRot;
float XScale, YScale, ZScale;
int *TextureImage;
BOOL Hidden, Culling, Transparency, WireFrame, Fog, Ambient, Lights, Filtering;
float RGBRed, RGBGreen, RGBBlue;
BOOL IsGhost;
int GhostMode;
int Diffuse, Ambience, Specular, Emissive, SpecularPower;
int *DetailMappingImage, Smoothing, AlphaMappingPercent;
}Object3DType;
/* 0. System functions unavailable to user */
Object3DType *Allocate3DObject( int ObjectID ){ // is line 49
Object3DType *NewObject = IExec -> AllocVecTags( sizeof( Object3DType ), TAG_DONE );
if ( !NewObject ){
return NULL;
}
// On modifie les param?tres de l'objet 3D fraichement cr?e.
NewObject->PreviousObject = Basic3D->LastCreatedObject;
NewObject.Exist = 1;
NewObject.ID = ObjectID;
NewObject->PreviousObject = Basic3D->LastCreatedObject;
NewObject.RGBRed = 255;
NewObject.RGBGreen = 255;
NewObject.RGBBlue = 255;
// On ins?re dans l'avant dernier objet 3D la r?f?rence du nouvel objet 3D.
Object3DType *OldObject = Basic3D->LastCreatedObject;
OldObject->NextObject = *NewObject;
// On ins?re le nouvel objet cr?e dans la structure de Basic3D.
Basic3D->LastCreatedObject = *NewObject;
Basic3D.B3DObjectAmount++;
return NewObject;
}
void BASIC3D_Destructor( void ){
// Suppression de tous les objets 3D existants restants.
if ( Basic3D.B3DObjectAmount > 0 ){
// On r?cup?re l'objet en m?moire en Basic3D
struct Object3DType *NewObject = Basic3D->LastCreatedObject;
do{
Basic3D.B3DObjectAmount--;
struct Object3DType *NextToDelete = NewObject->PreviousObject;
/* Free3DObject( *NewObject );*/
*NewObject = *NextToDelete;
} while ( !NewObject );
if ( Basic3D.B3DObjectAmount != NULL ){
// Afficher un message d'erreur si la quantit? d'objets restants est > 0 alors que la liste est vide.
}
}
}
And the errors : Quote:
Basic3D.c: In function 'Allocate3DObject': Basic3D.c:55: error: 'Basic3D' has an incomplete type Basic3D.c:56: error: request for member 'Exist' in something not a structure or union Basic3D.c:57: error: request for member 'ID' in something not a structure or union Basic3D.c:58: error: 'Basic3D' has an incomplete type Basic3D.c:59: error: request for member 'RGBRed' in something not a structure or union Basic3D.c:60: error: request for member 'RGBGreen' in something not a structure or union Basic3D.c:61: error: request for member 'RGBBlue' in something not a structure or union Basic3D.c:63: error: 'Basic3D' has an incomplete type Basic3D.c:64: error: incompatible types in assignment Basic3D.c:66: error: 'Basic3D' has an incomplete type Basic3D.c:67: error: invalid use of undefined type 'struct Basic3DStructType' Basic3D.c: In function 'BASIC3D_Destructor': Basic3D.c:83: error: invalid use of undefined type 'struct Basic3DStructType' Basic3D.c:85: error: 'Basic3D' has an incomplete type Basic3D.c:87: error: invalid use of undefined type 'struct Basic3DStructType' Basic3D.c:88: error: dereferencing pointer to incomplete type Basic3D.c:90: error: dereferencing pointer to incomplete type Basic3D.c:90: error: dereferencing pointer to incomplete type Basic3D.c:92: error: invalid use of undefined type 'struct Basic3DStructType'
All we have to decide is what to do with the time that is given to us.
I changed a little but I did not test if it compiles :
/* Structure de Basic 3D qui peut-?tre partag?e pour les donn?es*/
typedef struct {
int B3DObjectAmount;
int *ObjectList;
int *LastCreatedObject;
}Basic3DStructType;
Basic3DStructType Basic3D;
typedef struct {
BOOL Exist;
int *PreviousObject;
int *NextObject;
int ID;
int Type;
float XPos, YPos, ZPos;
float XRot, YRot, ZRot;
float XScale, YScale, ZScale;
int *TextureImage;
BOOL Hidden, Culling, Transparency, WireFrame, Fog, Ambient, Lights, Filtering;
float RGBRed, RGBGreen, RGBBlue;
BOOL IsGhost;
int GhostMode;
int Diffuse, Ambience, Specular, Emissive, SpecularPower;
int *DetailMappingImage, Smoothing, AlphaMappingPercent;
}Object3DType;
/* 0. System functions unavailable to user */
Object3DType *Allocate3DObject( int ObjectID ){ // is line 49
Object3DType *NewObject = IExec -> AllocVecTags( sizeof( Object3DType ), TAG_DONE );
if ( !NewObject ){
return NULL;
}
// On modifie les param?tres de l'objet 3D fraichement cr?e.
NewObject->PreviousObject = Basic3D.LastCreatedObject;
NewObject->Exist = 1;
NewObject->ID = ObjectID;
NewObject->PreviousObject = Basic3D.LastCreatedObject;
NewObject->RGBRed = 255;
NewObject->RGBGreen = 255;
NewObject->RGBBlue = 255;
// On ins?re dans l'avant dernier objet 3D la r?f?rence du nouvel objet 3D.
Object3DType *OldObject = Basic3D.LastCreatedObject;
OldObject->NextObject = NewObject;
// On ins?re le nouvel objet cr?e dans la structure de Basic3D.
Basic3D.LastCreatedObject = NewObject;
Basic3D.B3DObjectAmount++;
return NewObject;
}
void BASIC3D_Destructor( void ){
// Suppression de tous les objets 3D existants restants.
if ( Basic3D.B3DObjectAmount > 0 ){
// On r?cup?re l'objet en m?moire en Basic3D
Object3DType *NewObject = Basic3D.LastCreatedObject;
do{
Basic3D.B3DObjectAmount--;
Object3DType *NextToDelete = NewObject->PreviousObject;
/* Free3DObject( *NewObject );*/
*NewObject = *NextToDelete;
} while ( !NewObject );
if ( Basic3D.B3DObjectAmount != NULL ){
// Afficher un message d'erreur si la quantit? d'objets restants est > 0 alors que la liste est vide.
}
}
}
Basic3D.c:49: error: expected '=', ',', ';', 'asm' or '__attribute__' before '*' token Basic3D.c:71: error: expected ')' before '*' token Basic3D.c: In function 'BASIC3D_Destructor': Basic3D.c:83: error: 'Basic3D' undeclared (first use in this function) Basic3D.c:83: error: (Each undeclared identifier is reported only once Basic3D.c:83: error: for each function it appears in.) Basic3D.c:85: error: 'NewObject' undeclared (first use in this function) Basic3D.c:88: error: 'NextToDelete' undeclared (first use in this function)
All we have to decide is what to do with the time that is given to us.
is effectively creating variable myVar of type struct myStruct *but* this is done locally : your variable will only be visible and useable (like in "if you access it elsewhere you'll get a crash") in the current C block.
Using "typedef" can save you typing the reserved word "struct" everytime in front of your structure name, see examples below :
struct myStruct {
int ms_Member1;
int ms_Member2;
};
does *not* create an instance of struct myStruct but only *declaring* a pointer to a struct myStruct. I say that because it's *invalid* (like in "it will crash immediatly if you do it") do write this :
Before using a pointer you should tell it where to point, - First it's (very) good coding practise to initialize every pointer to NULL right after creating them like in
struct myStruct * myPointer = NULL;
if you don't do that its content is unpredictable (or at best is compiler dependant). - either allocate a new object by either using ANSI C malloc() either Amiga AllocVec() functions see examples below
Sidenote after an allocation it's better to test that allocation did not failed, for this test you pointer is not NULL. - either initialize with another (valid) variable examples
struct myStruct myVar;
struct myStruct * myPointer = &myVar; // myPointer points to myVar, i.e if I modify
// one I'll see same modification onthe other
struct myStruct * myPointer2 = myPointer; // myPointer2 is given the same (actual) value as myPointer,
// here this makes myPointrer2 to point to myVar
Final note on pointers : you *can't* return a pointer to a local variable following code is bad and will crash
You should really consider reading a C tutorial/manual about pointers as this is a bit difficult to understand if you never programmed C-like language before. Once you have understood that concept C is really a matter of fun, with some points of syntax details.
@abalaban I'm reading a book concerning C but this book is far to be as complete as the explanations I get here in the forums ...
I think I've understood each of your explanations ( I don't hide that I did read them several time to be sure ;) )... The only thing you don't cover is how to return a pointer. You said that I can't return pointer into a local var but how then ? it's the only missing thing I need I think to cover the pointers principles. In fact, I use the allocvec to create the structure and I want to get the structure pointer back from the creation function to another one (imagine in fact, I have a function to create the structure and initialize general data inside it and other functions that did create object will call this function to create the structure and they'll modify data to fit the final object specificities)
However, thank you for all these really importants explanations on pointers ... now I understand why much of the remaining errors I get in my code happen and I think I will be able to fix them ... My main error was to think that handling pointers in C was easier ... in fact, it's a bit more complex, but I think you've made an enough clear explanation to allow me to continue on my project.
Kindest Regards, Fred.
All we have to decide is what to do with the time that is given to us.
I think I've understood each of your explanations ( I don't hide that I did read them several time to be sure ;) )... The only thing you don't cover is how to return a pointer. You said that I can't return pointer into a local var but how then ? it's the only missing thing I need I think to cover the pointers principles. In fact, I use the allocvec to create the structure and I want to get the structure pointer back from the creation function to another one (imagine in fact, I have a function to create the structure and initialize general data inside it and other functions that did create object will call this function to create the structure and they'll modify data to fit the final object specificities)
When I was speaking of "local variables" I meant variables that are allocated by the compiler, not the one that you are allocating using either malloc/AllocVec functions. Those are safe to return from a function, because they are valid until you deallocate the corresponding memory using free()/FreeVec() while local variables are automatically freed (or at least not accessible) when you exit the block where it was defined in (try to document yourself on variable's scope (in french "la port?e des variables"))
@abalaban if the variable is in a block {...} then the variable is local to this block. if the variable is defined outside blocks ... then it become available from each block of the C code ... this variable is then global .. Isn't this right ?
I've made changes to my source code using your explanations and now I get no more compiling error :)
Here is the source code :
/* Structure de Basic 3D qui peut-?tre partag?e pour les donn?es*/
struct Basic3DStruct{
int ObjectAmount;
int *ObjectList;
int *LastCreatedObject;
};
struct Basic3DStruct Basic3D;
struct Object3DStruct{
BOOL Exist;
int *PreviousObject;
int *NextObject;
int ID;
int Type;
float XPos, YPos, ZPos;
float XRot, YRot, ZRot;
float XScale, YScale, ZScale;
int *TextureImage;
BOOL Hidden, Culling, Transparency, WireFrame, Fog, Ambient, Lights, Filtering;
float RGBRed, RGBGreen, RGBBlue;
BOOL IsGhost;
int GhostMode;
int Diffuse, Ambience, Specular, Emissive, SpecularPower;
int *DetailMappingImage, Smoothing, AlphaMappingPercent;
};
typedef struct Object3DStruct Object3DType;
//* 0. System functions unavailable to user */
Object3DType *Allocate3DObject( int ObjectID ){ // is line 49
Object3DType *NewObject = IExec -> AllocVecTags( sizeof( Object3DType ), TAG_DONE );
if ( !NewObject ){
return NULL;
}
// On modifie les param?tres de l'objet 3D fraichement cr?e.
NewObject->PreviousObject = Basic3D.LastCreatedObject;
NewObject->Exist = 1;
NewObject->ID = ObjectID;
NewObject->PreviousObject = Basic3D.LastCreatedObject;
NewObject->RGBRed = 255;
NewObject->RGBGreen = 255;
NewObject->RGBBlue = 255;
// On ins?re dans l'avant dernier objet 3D la r?f?rence du nouvel objet 3D.
Object3DType *OldObject = Basic3D.LastCreatedObject;
OldObject->NextObject = NewObject;
// On ins?re le nouvel objet cr?e dans la structure de Basic3D.
Basic3D.LastCreatedObject = NewObject;
++Basic3D.ObjectAmount;
return NewObject;
}
void BASIC3D_Destructor( void ){
// Suppression de tous les objets 3D existants restants.
if ( Basic3D.ObjectAmount != 0 ){
// On r?cup?re l'objet en m?moire en Basic3D
Object3DType *NewObject = Basic3D.LastCreatedObject;
do{
--Basic3D.ObjectAmount;
Object3DType *NextToDelete = NewObject->PreviousObject;
/* Free3DObject( *NewObject );*/
*NewObject = *NextToDelete;
} while ( !NewObject );
if ( Basic3D.ObjectAmount != 0 ){
// Afficher un message d'erreur si la quantit? d'objets restants est > 0 alors que la liste est vide.
}
}
}
[edit] Of course, there are changes I must do in this source code but actually it compiles :)
Edited by freddix on 2009/3/3 0:35:42
All we have to decide is what to do with the time that is given to us.
After a quick read I would say this seems fine, except one thing : you should initialize NewObject->NextObject to NULL in Allocate3DObject() else your BASIC3D_Destructor() won't stop at the last object (because !NewObject might not be true). I would also recommend you to initialize your Basic3D object in your BASIC3D_Constructor() like this :
If it were my code I would probably turn Basic3D into a pointer initialized to NULL, this way I would be able to identify when people had called my BASIC3D_Constructor() or not (by just testing against NULL), this can then look like this :
EDIT: Oh one potential bug in your Allocate3DObject() please test OldObject against NULL (this is the case when Basic3D list is empty) like this :
// On ins?re la r?f?rence du nouvel objet 3D dans le dernier objet 3D (s'il y en a un)
Object3DType *OldObject = Basic3D.LastCreatedObject;
if( OldObject ) {
OldObject->NextObject = NewObject;
}
EDIT2: in fact your structure is strangely used i guess the code should better look like this :
// On ins?re la r?f?rence du nouvel objet 3D dans le dernier objet 3D (s'il y en a un)
Object3DType *OldObject = Basic3D.LastCreatedObject;
if( OldObject ) {
OldObject->NextObject = NewObject;
} else {
Basic3D.ObjectList = NewObject;
}
EDIT3: AmigaOS has structure and functions to manage linked lists, look at exec.library/AddTail, exec.library/AddHead, etc. and struct List and struct Node.
@abalaban Yeah you're right some of these changes were planed ;) Concerning BASIC3D_Constructor() the function is not used by users but internal initialisation of the system there will be both Constructor and Destructor for each set of commands ( Basic3D, Camera, Music, Sound, etc ... )
Thank you.
All we have to decide is what to do with the time that is given to us.
freddix wrote: @abalaban Yeah you're right some of these changes were planed ;) Concerning BASIC3D_Constructor() the function is not used by users but internal initialisation of the system there will be both Constructor and Destructor for each set of commands ( Basic3D, Camera, Music, Sound, etc ... )
Thank you.
When I was speaking of "user" it was on the abstract side : i.e. any code that is using your functions. Anyway if you don't initialize Basic3D in its constructor you would have problems in its destructor (ObjectAmount value is unpredictable if it's not initialized). Looking at your code maybe that's C++ that you should have learnt instead of C (C++ is an Object Oriented language using C syntax, in fact it's a superset of C). in c++ you could have written :
// declaration de la classe Object3DClass *sans* definition du code
// cela permet d'utiliser de d?clarer des structures/classes utilisant
// *des pointeurs* Object3DClass alors que la classe n'est pas encore d?finie
class Object3DClass;
// definition de la classe Basic3D
class Basic3DClass {
private:
int ObjectAmount;
Object3DClass *ObjectList;
Object3DClass *LastCreatedObject;
public:
Basic3DClass() {
// c'est un constructeur C++, noter qu'il n'y a pas de valeur de retour
ObjectAmount = 0;
ObjectList = NULL;
LastCreatedObject = NULL;
}
~Basic3DClass() {
// Suppression de tous les objets 3D existants restants.
if ( ObjectAmount != 0 ){
// On r?cup?re l'objet en m?moire en Basic3D
Object3DClass *NewObject = LastCreatedObject;
do{
--ObjectAmount;
Object3DType *NextToDelete = NewObject->PreviousObject;
/* delete NewObject;*/ // <- note voil? comment on efface un objet allou? dynamiquement en c++
*NewObject = *NextToDelete;
} while ( !NewObject );
if ( ObjectAmount != 0 ){
// Afficher un message d'erreur si la quantit? d'objets restants est > 0 alors que la liste est vide.
}
}
}
void InsertObject3D( object3DClass * NewObject ) {
NewObject->PreviousObject = LastCreatedObject;
// On ins?re la r?f?rence du nouvel objet 3D dans le dernier objet 3D (s'il y en a un)
Object3DType *OldObject = LastCreatedObject;
if( OldObject ) {
OldObject->NextObject = NewObject;
} else {
ObjectList = NewObject;
}
// On ins?re le nouvel objet cr?e dans la structure de Basic3D.
LastCreatedObject = NewObject;
++ObjectAmount;
}
}
// definition de la classe Object3DClass
class Object3DClass {
private:
BOOL Exist;
Object3DClass *PreviousObject;
Object3DClass *NextObject;
int ID;
int Type;
float XPos, YPos, ZPos;
float XRot, YRot, ZRot;
float XScale, YScale, ZScale;
int *TextureImage;
BOOL Hidden, Culling, Transparency, WireFrame, Fog, Ambient, Lights, Filtering;
float RGBRed, RGBGreen, RGBBlue;
BOOL IsGhost;
int GhostMode;
int Diffuse, Ambience, Specular, Emissive, SpecularPower;
int *DetailMappingImage, Smoothing, AlphaMappingPercent;
public:
Object3DClass( int ObjectID ) {
// On modifie les param?tres de l'objet 3D fraichement cr?e.
Exist = 1;
ID = ObjectID;
RGBRed = 255;
RGBGreen = 255;
RGBBlue = 255;
PreviousObject = NULL;
NextObject = NULL;
}
~Object3DClass{
}
}
Basic3DClass Basic3D; // C++ appel automatiquement le constructeur associ?.
int main( void ) {
// on cr?e un object dynamiquement en c++, ce qui appelle automatiquement le constructeur ad?quat
Object3DClass * myObject = new Object3DClass( 1 );
if( myObject ) {
Basic3D.InsertObject3D( myObject );
}
yes the AOS4 SDK provides G++. In c++ source file extension are traditionnally .cpp instead of .c (.h stays even if some used to use .hpp, it's marginal now).
@abalaban Ok. It's what I seemed to see in the SDK folders ... Now I must find a C++ book to learn :p but waiting for this, I will probably continue a bit on C...
Are these much differencies between C and C++ ?
All we have to decide is what to do with the time that is given to us.
C++ is object oriented so you can group data and functions using them in the same structure called a class, you have inheritance, and with it polymorphism. C++ also has templates. You can define visibility protection too (public, protected and private) that's already much interesting things to learn Contrary to what people think no need to know C before learning C++ (I would even say it can be an drawback to know it before starting C++).