PB procedures + structures + freeing memory errors

Everything else that doesn't fall into one of the other PB categories.
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

PB procedures + structures + freeing memory errors

Post 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?
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post 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
User avatar
GedB
Addict
Addict
Posts: 1313
Joined: Fri May 16, 2003 3:47 pm
Location: England
Contact:

Post by GedB »

dracflamloc,

What does the code wrapping the dll call look like?

Is it a Tailbite PureLibrary, or a source include?
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post 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
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

I tried to make my wrapper functions into a library with tailbite but I couldnt get it working.
User avatar
GedB
Addict
Addict
Posts: 1313
Joined: Fri May 16, 2003 3:47 pm
Location: England
Contact:

Post 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.
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post 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
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post 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.
User avatar
GedB
Addict
Addict
Posts: 1313
Joined: Fri May 16, 2003 3:47 pm
Location: England
Contact:

Post by GedB »

What does the code look like?
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post 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]
User avatar
GedB
Addict
Addict
Posts: 1313
Joined: Fri May 16, 2003 3:47 pm
Location: England
Contact:

Post by GedB »

When and how does 'pb_scene' get initialised?
Post Reply