Page 1 of 1

PB procedures + structures + freeing memory errors

Posted: Thu Jan 06, 2005 12:59 am
by dracflamloc
I'm having an issue with passing/returning structures and freeing the memory afterwards.

Here's the PB code:

Code: Select all

Structure I3D_NODEDATA
  xPos.f
  yPos.f
  zPos.f
EndStructure

ProcedureDLL.l i3D_Node_GetData(nodeID.l) ; Gets the nodes data in a structure
  *tmpNodeData.I3D_NODEDATA = AllocateMemory(SizeOf(I3D_NODEDATA))
  *tmpNodeData = CallCFunction(i3D_Library,"pb_Node_GetData",nodeID)
  ProcedureReturn *tmpNodeData
EndProcedure

In a loop I have:
    ExamineKeyboard() 
    If KeyboardReleased(#PB_Key_Escape)
      i3D_Close3D()
    ElseIf KeyboardPushed(#PB_Key_Left)
      *ShipData.I3D_NODEDATA = i3D_Node_GetData(1)
      i3D_Node_SetPosition(1,*ShipData\xPos + 0.05,0,0)
      FreeMemory(*ShipData)
    ElseIf KeyboardPushed(#PB_Key_Right)
      *ShipData.I3D_NODEDATA = i3D_Node_GetData(1)
      i3D_Node_SetPosition(1,*ShipData\xPos - 0.05,0,0)
      FreeMemory(*ShipData)
    EndIf

Code: Select all

//Get node data
API I3D_NODEDATA * CALLCONV pb_Node_GetData(int nodeID)
{
	I3D_NODEDATA *data = new I3D_NODEDATA;
	
	ISceneNode *node = pb_scene->getSceneNodeFromId(nodeID);
	
	data->xPos=node->getAbsolutePosition().X;
	data->yPos=node->getAbsolutePosition().Y;
	data->zPos=node->getAbsolutePosition().Z;
	return data;
}
It works fine at first, but the problem I get is after about five seconds of holding the arrow keys to move, i get a "Instruction tried to read memory at address 0x00000000" error.

Any ideas? I've never tried passing structures through pb before so maybe I missed something obvious?

Posted: Thu Jan 06, 2005 2:37 am
by dracflamloc
Ok after a little research I found that to fix it you can do this:

Code: Select all

//Get node data
API void CALLCONV pb_Node_GetData(int nodeID,I3D_NODEDATA * nodeStruct)
{
	ISceneNode *node = pb_scene->getSceneNodeFromId(nodeID);
	
	nodeStruct->xPos=node->getAbsolutePosition().X;
	nodeStruct->yPos=node->getAbsolutePosition().Y;
	nodeStruct->zPos=node->getAbsolutePosition().Z;

	return nodeStruct;
}

Code: Select all

ProcedureDLL i3D_Node_GetData(nodeID.l,*ReturnStruct.I3D_NODEDATA) ; Gets the nodes data in a structure
  CallCFunction(i3D_Library,"pb_Node_GetData",nodeID,*ReturnStruct)
EndProcedure
     ShipData.I3D_NODEDATA
    ;check keypress
    ExamineKeyboard() 
    If KeyboardReleased(#PB_Key_Escape)
      i3D_Close3D()
    ElseIf KeyboardPushed(#PB_Key_Left)
      i3D_Node_GetData(1,@ShipData)
      i3D_Node_SetPosition(1,ShipData\xPos - 0.05,0,0)
    ElseIf KeyboardPushed(#PB_Key_Right)
      i3D_Node_GetData(1,@ShipData)
      i3D_Node_SetPosition(1,ShipData\xPos + 0.05,0,0)
    EndIf

Posted: Thu Jan 06, 2005 10:00 am
by GedB
dracflamloc,

What does the code wrapping the dll call look like?

Is it a Tailbite PureLibrary, or a source include?

Posted: Thu Jan 06, 2005 4:11 pm
by dracflamloc

Code: Select all

ProcedureDLL i3D_Node_GetData(nodeID.l,*ReturnStruct.I3D_NODEDATA) ; Gets the nodes data in a structure
  CallCFunction(i3D_Library,"pb_Node_GetData",nodeID,*ReturnStruct)
EndProcedure

Posted: Thu Jan 06, 2005 4:11 pm
by dracflamloc
I tried to make my wrapper functions into a library with tailbite but I couldnt get it working.

Posted: Thu Jan 06, 2005 4:31 pm
by GedB
Shouldn't you be using a procedure return?

The method you're using to wrap dlls will have a performance penalty, since it will have to look up the call in the dll with every time.

Have you tried the DLLImporter yet? It is the quickest and simplest way.

Posted: Thu Jan 06, 2005 5:05 pm
by dracflamloc
When I'm done I will use the CallCFunctionFast. I just tried DLL Importer again and this time it worked. Dunno what I did differently, but this should make things better now.

Just for kicks here's the pbl file I created for PB_Irrlicht.dll:

Code: Select all

; PureBasic DLL import file
;
PB_IRRLICHT.DLL
pb_Initialize3D 7
pb_Running 0
pb_Close3D 0
pb_DoCleanUp 0
pb_GetFPS 0
pb_SetBackgroundColor 4
pb_BeginRender 2
pb_EndRender 0
pb_DrawGUI 0
pb_DrawScene 0
pb_SetWindowCaption 1
pb_SetShadowColor 4
pb_GUI_SetFont 1
pb_GUI_CreateEditBox 7
pb_GUI_CreateButton 6
pb_GUI_CreateStaticText 8
pb_GUI_CreateMessageBox 5
pb_Draw2DText 9
pb_LoadTexture 1
pb_LoadMesh 1
pb_CreateAnimatedNode 6
pb_CreateDynamicLight 9
pb_Camera_PointAtNode 1
pb_Camera_SetRotation 3
pb_Node_SetTexture 3
pb_Node_SetRotation 4
pb_Node_SetPosition 4
pb_Node_GetData 2
pb_Node_SetMaterialType 2
pb_Node_SetMaterialFlag 3

Posted: Thu Jan 06, 2005 5:49 pm
by dracflamloc
every command works it seems except quite possibly the most important: It won't create the 3d object. It doesn't crash when I use the command, but it just doesnt display it. The call works from my previous pb code however...

Also I just noticed that if you click the Wireframe button in my example, it doesnt work (So theres a problem with the event handler)

But theres not a null-reference (access 0x00000000) error with the Node commands because I can get the x/y/z position of it no problem.

Posted: Thu Jan 06, 2005 6:14 pm
by GedB
What does the code look like?

Posted: Thu Jan 06, 2005 6:46 pm
by dracflamloc
When trying to get the returned value of this the exe crashes, or if you don't try and use the return value the program will keep running but not show the 3d node.

Code: Select all

//Add an animated scene node
API int CALLCONV pb_CreateAnimatedNode(char * fileName,int meshID,float scaleX,float scaleY,float scaleZ,int isLighting)
{
	IAnimatedMeshSceneNode *node=pb_scene->addAnimatedMeshSceneNode(pb_scene->getMesh(fileName),0,meshID,vector3df(0,0,0),vector3df(0,0,0),vector3df(scaleX,scaleY,scaleZ));
	node->setMaterialFlag(video::EMF_LIGHTING, pb_intToBool(isLighting));
	return node->getID();
}
Yet this works fine and the returned value is correct and does not crash the exe:

Code: Select all

//Create button
API int CALLCONV pb_GUI_CreateButton(char * text,int guiID,int x,int y,int x2,int y2)
{
	stringw k=L"";
	k += text;
	IGUIButton *btn=pb_gui->addButton(rect<s32>(x,y,x2,y2),0,guiID,k.c_str());
	return btn->getID();
}

And the PB code thats calling all this:

Code: Select all

ProcedureCDLL EventHandler(*EventData.I3D_GUI_EVENT)
  If *EventData\eventType=#I3D_GUIEVENT_BUTTON_CLICKED
    LastGuiID=*EventData\guiID
  EndIf
EndProcedure

Procedure HandleGUIEvent(guiID.l)
  If guiID=102 
    pb_Node_SetMaterialFlag_(1,#I3D_MATERIALFLAG_WIREFRAME,1)
  EndIf
EndProcedure

ShipData.I3D_NODEDATA
If pb_Initialize3D_(#I3D_DRIVER_OPENGL, 640,480,32,0,1,@EventHandler()) 
  ;set startup values
  InitKeyboard() 
  pb_SetShadowColor_(255,0,0,0)
  pb_SetBackgroundColor_(155,90,90,90)
  pb_SetWindowCaption_("Test PB_Irrlicht")
  pb_GUI_SetFont_("./fontcourier.bmp")
  pb_LoadMesh_("./ship1.ms3d")
  pb_LoadTexture_("./ship1.bmp")
  pb_CreateAnimatedNode_("./ship1.ms3d",1,1,1,1,1)
  pb_Node_SetMaterialType_(1,#I3D_MATERIALTYPE_SPHERE_MAP)
  pb_Node_SetTexture_("./ship1.bmp",1,0) 
  pb_CreateDynamicLight_(1,5,5,5,100,255,255,255,100)
  pb_Camera_SetPosition_(20,50,20)
  
  ;create GUI
  EditBox1.l = pb_GUI_CreateEditBox_("Edit box sample",101,100,100,250,150,1)
  Button1.l = pb_GUI_CreateButton_("Wireframe",102,400,100,500,150)
  Static1.l = pb_GUI_CreateStaticText_("Static text is fun!",103,250,250,400,300,0,0)
  MsgBox.l = pb_GUI_CreateMessageBox_("Test MsgBox","Testing 1 2 3",104,1,#I3D_GUI_MSGBOX_OK + #I3D_GUI_MSGBOX_CANCEL)
  
  lastFPS.l=0
  While pb_Running_()
    pb_Camera_PointAtNode_(1)
    
    ;Render the scene
    pb_BeginRender_(1,1)
    
    pb_Draw2DText_("./fontcourier.bmp",10,10,"Hello and welcome to PB_Irrlicht by dracflamloc!",255,255,255,255,0)
    pb_Draw2DText_("./fontcourier.bmp",10,30,"http://www.dracsoft.com/",255,255,255,255,0)
    pb_Draw2DText_("./fontcourier.bmp",10,50,"X: " + Str(ShipData\xPos),255,255,255,255,0)
    pb_Draw2DText_("./fontcourier.bmp",10,70,"Z: " + Str(ShipData\zPos),255,255,255,255,0)
    pb_DrawScene_()
    pb_DrawGUI_()
    
    pb_EndRender_()
    
    ;check fps and update titlebar
    If lastFPS<>pb_GetFPS_()
      lastFPS = pb_GetFPS_()
      pb_SetWindowCaption_("Test PB_Irrlicht - " + Str(lastFPS) + " FPS")
    EndIf
    
    ;rotate object
    pb_Node_GetData_(1,@ShipData)
    pb_Node_SetRotation_(1,ShipData\xRot+0.05,ShipData\yRot+0.05,ShipData\zRot-0.05)
    
    ;check keypress
    ExamineKeyboard() 
    If KeyboardReleased(#PB_Key_Escape)
      pb_Close3D_()
    ElseIf KeyboardPushed(#PB_Key_Left)
      pb_Node_GetData_(1,@ShipData)
      pb_Node_SetPosition_(1,ShipData\xPos - 0.05,ShipData\yPos,ShipData\zPos)
    ElseIf KeyboardPushed(#PB_Key_Right)
      pb_Node_GetData_(1,@ShipData)
      pb_Node_SetPosition_(1,ShipData\xPos + 0.05,ShipData\yPos,ShipData\zPos)
    ElseIf KeyboardPushed(#PB_Key_Up)
      pb_Node_GetData_(1,@ShipData)
      pb_Node_SetPosition_(1,ShipData\xPos,ShipData\yPos,ShipData\zPos - 0.05)
    ElseIf KeyboardPushed(#PB_Key_Down)
      pb_Node_GetData_(1,@ShipData)
      pb_Node_SetPosition_(1,ShipData\xPos,ShipData\yPos,ShipData\zPos + 0.05)
    EndIf
    
    ;for now use the global to handle the gui event
    HandleGUIEvent(LastGuiID)
  Wend 
Else
  MessageRequester("Error","Could not initialize the 3D device.")
EndIf

pb_DoCleanUp_()
End
[/code]

Posted: Thu Jan 06, 2005 10:05 pm
by GedB
When and how does 'pb_scene' get initialised?