Pyrex and embedding Panda3D

Hello,
this is just a little experiment I made the last 15 minutes. I’m afraid there is nothing really useful in here right now, but it is rather nice from the technical side.

from direct.showbase.DirectObject import DirectObject
import sys

class World( DirectObject ):

    def __init__( self ):
        base.setBackgroundColor( 0.0, 0.0, 0.3, 1.0 )

        self.accept( 'escape', self.exit )

        self.np = loader.loadModel( 'models/camera' )
        self.np.reparentTo( render )
        self.np.setPos( 0, 10, 0 )

        taskMgr.add( self.update, 'update' )

    def exit( self ):
        sys.exit( )

    def update( self, task ):
        self.np.setH( task.time * 90.0 )
        return task.cont

import direct.directbase.DirectStart
world = World( )
run( )

Not the most complex Panda3D script I ever wrote, but it has some Panda3D stuff in it (open a window, register a key for closing the window, load a model, and rotate the model using a task). And it is a plain Python file.

Now I add some lines and rename the file to “PandaTest.pyx”:

from direct.showbase.DirectObject import DirectObject
import sys

class World( DirectObject ):

    def __init__( self ):
        base.setBackgroundColor( 0.0, 0.0, 0.3, 1.0 )

        self.accept( 'escape', self.exit )

        self.np = loader.loadModel( 'models/camera' )
        self.np.reparentTo( render )
        self.np.setPos( 0, 10, 0 )

        taskMgr.add( self.update, 'update' )

    def exit( self ):
        sys.exit( )

    def update( self, task ):
        self.np.setH( task.time * 90.0 )
        return task.cont



cdef extern from 'Python.h':
    void Py_Initialize( )
    void Py_Finalize( )
    void PySys_SetArgv( int argc, char **argv )

cdef public void initPandaTest( )

cdef public int main( int argc, char **argv ):

    Py_Initialize( )
    PySys_SetArgv( argc, argv )
    initPandaTest( )
 
    import direct.directbase.DirectStart
    world = World( )
    run( )

    Py_Finalize( )

This is no longer Python code, but Pyrex code. Running Pyrex generates C/C++ code. Compile the cpp file, and you get a binary. “.exe” in my case, since I’m on windows.

I have used Pyrex mainly for extending and speeding up Python so far, but this short code shows it is also easy to embed Python. This script has no benefit from Pyrex (no speed gain), except that your own code is well hidden now.

enn0x

So with this technique one could make executables instead of using the PackPanda utility! If so thats awesome.

How would you compile that C++ code once pyrex is done :question:

Great work regardless

No, I’m afraid this is no replacement for PandaPack. What you see is basically funny written C code, which (function main) initializes the Python interpreter and then makes it execute several Python commands. Like you would in in the Python shell. So for “import xyz” the module “xyz” has to be somewhere on the search path. The Python interpreter runs embedded in C++ code.

Pyrex is mainly useful for extending Python. Your camera control code is too slow? Why not write a small extension which does the math in C and not in Python, and use the Panda C API instead of the Python API. Hmmm… I should put a small demo here, on how to use Pyrex.

How to compile: Well, this is dependent on what compiler you use. In my case it is VC 2003 Toolkit (no IDE). My makefile looks like this:

CC = cl
LINK = link
PYREX = "%ProgramFiles%\Python\Scripts\pyrexc.py"

CFLAGS = /nologo /DWIN32_VC /DWIN32 /DNDEBUG /Ox /GX /wd4005 /MT /D_NEWTON_USE_LIB
LDFLAGS = /nologo
LIBS = libpandaegg.lib libpanda.lib libp3dtool.lib libpandaexpress.lib libp3dtoolconfig.lib

all: clean PandaTest.exe

PandaTest.exe : PandaTest.obj
	$(LINK) $(LDFLAGS) /OUT:$@ $< $(LIBS)

PandaTest.obj : PandaTest.cpp
	$(CC) $(CFLAGS) /c $< /Fo$@

PandaTest.cpp :
	$(PYREX) PandaTest.pyx -o $@

clean:
	rm -f *.obj *.exp *.lib *.cpp

Oh, and of course the Panda3D python headers and libs have to be on your path and not the default ones.

enn0x

I see…:confused:

Thank you for the clarification. I can already think of some uses for this as it was intended to do. Thanks for sharing