[Bf-python] Pyrex - an easier way to write Python/C modules?
Yann Vernier
yann at algonet.se
Sat Nov 6 14:09:30 CET 2004
I messed around a while, and eventually got a drop in replacement for
Blender.Text working. Pyrex is written in Python, and could be better
integrated with scons than this - it already has a module to extend
distutils.
http://nz.cosc.canterbury.ac.nz/~greg/python/Pyrex/
--
PGP fingerprint = 9242 DC15 2502 FEAB E15F 84C6 D538 EC09 5380 5746
-------------- next part --------------
Index: SConscript
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/python/SConscript,v
retrieving revision 1.20
diff -u -r1.20 SConscript
--- SConscript 21 Sep 2004 05:28:17 -0000 1.20
+++ SConscript 6 Nov 2004 12:47:38 -0000
@@ -42,7 +42,7 @@
'api2_2x/Window.c',
'api2_2x/World.c',
'api2_2x/Image.c',
- 'api2_2x/Text.c',
+ #'api2_2x/Text.c',
'api2_2x/Texture.c',
'api2_2x/Noise.c',
'api2_2x/charRGBA.c',
@@ -73,4 +73,13 @@
python_env.Append (CPPPATH = user_options_dict['PYTHON_INCLUDE'])
python_env.Append (CPPPATH = user_options_dict['OPENGL_INCLUDE'])
python_env.Append (CPPPATH = extra_includes)
-python_env.Library (target='#'+user_options_dict['BUILD_DIR']+'/lib/blender_python', source=source_files)
+
+pyrexbuild = Builder(action = 'pyrexc -o $TARGET $SOURCE',
+ suffix = python_env['CFILESUFFIX'], src_suffix = '.pyx')
+python_env.Append (BUILDERS = {'Pyrex': pyrexbuild})
+
+textc = python_env.Pyrex('api2_2x/Text')
+texth = python_env.SideEffect('api2_2x/Text.h', textc)
+
+python_env.Library (target='#'+user_options_dict['BUILD_DIR']+'/lib/blender_python', source=source_files+[textc])
+
-------------- next part --------------
cdef extern from "DNA_ID.h":
struct ID:
void *next
#void *prev
#ID *newid
#Library *lib
char name[24]
#short us
#short flag
#int pad
cdef extern from "DNA_listBase.h":
struct Link:
Link *next
Link *prev
struct ListBase:
void *first
void *last
cdef extern from "DNA_text_types.h":
struct TextLine:
TextLine *next
TextLine *prev
char *line
int len
int blen
struct Text:
ID id
char *name
int flags
int nlines
ListBase lines
#TextLine *curl
#TextLine *sell
#int curc
#int selc
#char *undo_buf
#int undo_pos
#int undo_len
#void *compiled
enum:
TXT_FOLLOW
cdef extern from "BKE_library.h":
void rename_id(ID *id, char *name)
void free_libblock(ListBase *lb, void *idv)
void free_libblock_us(ListBase *lb, void *idv)
cdef extern from "BKE_main.h":
struct Main:
ListBase text
cdef extern from "BKE_global.h":
struct Global:
Main *main
Global G
-------------- next part --------------
from blenkernel cimport Text as c_Text
cdef public class Text [object BPy_Text, type Text_Type]:
cdef c_Text *text
-------------- next part --------------
"The Blender Text module"
from blenkernel cimport G, \
Text as c_Text, TextLine, TXT_FOLLOW, \
free_libblock, rename_id
cdef extern from "BKE_text.h":
c_Text *add_empty_text()
c_Text *add_text(char *file)
int txt_get_undostate()
void txt_set_undostate(int)
void txt_sel_all(c_Text*)
void txt_cut_sel(c_Text*)
void txt_insert_buf(c_Text *text, char *in_buffer)
void txt_move_eof(c_Text *text, short sel)
cdef int isLinked(Text text):
cdef c_Text *iter
if text.text is NULL:
return 0
iter=<c_Text*>G.main.text.first
while iter:
if iter == text.text:
return 1
iter=<c_Text*>iter.id.next
# Here's a problem, this Text is invalid.
text.text=NULL
return 0
cdef int checkLinked(Text text) except 0:
if text.text and isLinked(text):
return 1
else:
raise RuntimeError("This object isn't linked to a Blender Text Object")
cdef public class Text [object BPy_Text, type Text_Type]:
"Blender Text"
def getName(self):
"() - Return Text Object name"
checkLinked(self)
# A bit clumsy, but slicing causes the string conversion to be done first.
return self.text.id.name+2
def setName(self, name):
"(str) - Change Text Object name"
checkLinked(self)
# Note: length check is absent here.
# rename_id should check, hardcoding all over is bad.
rename_id(&self.text.id, name)
property name:
"The Text name."
checkLinked(self)
def __get__(self):
return self.getName()
def __set__(self, value):
self.setName(value)
def getFilename(self):
"() - Return Text Object filename"
checkLinked(self)
if self.text.name is not NULL:
return self.text.name
property filename:
def __get__(self):
return self.getFilename()
property mode:
def __get__(self):
checkLinked(self)
return self.text.flags
def getNLines(self):
"() - Return number of lines in text buffer"
# Apparently this isn't updated in Blender itself, by comments in Text.c
cdef TextLine *line
cdef int nlines
checkLinked(self)
nlines=0
line=<TextLine*>self.text.lines.first
while line:
nlines=nlines+1
line=line.next
self.text.nlines=nlines
return nlines
property nlines:
def __get__(self):
return self.getNLines()
def clear(self):
"() - Clear Text buffer"
cdef int oldstate
checkLinked(self)
oldstate=txt_get_undostate()
txt_set_undostate(1)
txt_sel_all(self.text)
txt_cut_sel(self.text)
txt_set_undostate(oldstate)
def write(self, char *line):
"(line) - Append string 'str' to Text buffer"
cdef int oldstate
checkLinked(self)
oldstate=txt_get_undostate()
txt_insert_buf(self.text, line)
txt_move_eof(self.text, 0)
txt_set_undostate(oldstate)
def set(self, char *name, int val):
"(name, val) - Set attribute 'name' to value 'val'"
checkLinked(self)
if name == "follow_cursor":
if val:
self.text.flags = self.text.flags|TXT_FOLLOW
else:
self.text.flags = self.text.flags&~TXT_FOLLOW
def asLines(self):
"() - Return text buffer as a list of lines"
cdef TextLine *line
checkLinked(self)
line=<TextLine*>self.text.lines.first
res=[]
while line:
res.append(line.line)
line=line.next
return res
def __cmp__(self, Text other not None):
if self.text is other.text:
return 0
else:
return -1
def __repr__(self):
if self.text and isLinked(self):
return '[Text "%s"]'%(self.text.id.name+2)
else:
return '[Text <deleted>]'
#cdef extern from "string.h":
# int strcmp(char*,char*)
def Get(name=None):
"""(name) - return the Text with name 'name', \
returns None if not found.\n If 'name' is not specified, \
it returns a list of all Texts in the\ncurrent scene."""
cdef c_Text *iter
cdef Text txt
cdef char *wantedname
iter=<c_Text*>G.main.text.first
if name is not None:
wantedname=name
while iter:
if strcmp(iter.id.name+2, wantedname) == 0:
txt=Text()
txt.text=iter
return txt
iter=<c_Text*>iter.id.next
raise NameError('Text "%s" not found'%name)
else:
res=[]
while iter:
txt=Text()
txt.text=iter
res.append(txt)
iter=<c_Text*>iter.id.next
return res
# This warning didn't get a proper traceback.
#cdef extern from *:
# # Pointer types wrong. Why doesn't extern object work? How do you deal with borrowed refs?
# int PyErr_Warn(void* category, char *message) except -1
# void* PyExc_DeprecationWarning
def get(*args, **kwargs):
"Obsolete name for Blender.Text.Get()"
#PyErr_Warn(PyExc_DeprecationWarning, "Blender.Text.get() is deprecated - use Blender.Text.Get()")
return Get(*args, **kwargs)
def New(name=None, int follow_cursor=0):
"(name=None, follow_cursor=0) - return a new Text object"
cdef c_Text *bl_text
cdef Text text
bl_text=add_empty_text()
if not bl_text:
raise RuntimeError("couldn't create Text Object in Blender")
text=Text()
text.text=bl_text
if follow_cursor:
bl_text.flags = bl_text.flags|TXT_FOLLOW
if name is not None:
rename_id(&bl_text.id, name)
return text
def Load(char *filename):
"(filename) - return text from file filename as a Text Object, \
returns None if not found.\n"
cdef Text txt
txt=Text()
txt.text=add_text(filename)
if txt.text is NULL:
raise IOError("couldn't load text")
return txt
cdef extern from "../BPY_extern.h":
void BPY_clear_bad_scriptlinks(c_Text *byebye)
cdef extern from "BKE_sca.h":
void free_text_controllers(c_Text *txt)
cdef extern from "BIF_drawtext.h":
void unlink_text(c_Text *text)
def unlink(Text text not None):
"(text) - remove Text object 'text' from Blender"
if text.text is NULL:
raise RuntimeError("this text was already unlinked!")
BPY_clear_bad_scriptlinks(text.text)
free_text_controllers(text.text)
unlink_text(text.text)
free_libblock(&G.main.text, text.text)
text.text=NULL
# These two are auto-generated by Pyrex
cdef extern from *: # These are declared "elsewhere"; actually, in Pyrex.
void *module "__pyx_m"
void PyErr_Print()
void* PyErr_Occurred()
# But this one still needs a prototype.. *sigh*
# Also don't know quite how to do error checking, so we don't.
cdef public void initText() #except *
# Blender uses these
cdef public object Text_Init():
initText()
if PyErr_Occurred():
PyErr_Print()
# Note: Unlike the old Blender.Text module, we keep another reference ourselves.
return <object>module
cdef public object Text_CreatePyObject(c_Text *text):
cdef Text txt
txt=Text()
txt.text=text
return txt
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.blender.org/pipermail/bf-python/attachments/20041106/32e2a192/attachment.sig>
More information about the Bf-python
mailing list