This is known issue, since digitizer uses wxPseudoDC class which is not
part of wxWidgets but only wxPython related, you need to create manually
link to Python extension _gdi_.so. See
source:grass/trunk/gui/wxpython/README.
Solution provided by README is not an option - installation procedure CAN
NOT modify directly stuff outside of sandbox. I can create symlinks within
GRASS source ($WORKDIR), but not in /usr/*
Same problem here on OSX. At least on OSX I can directly link in the
_gdi_.so binary with a full path. Or you can create the symlink in some
place you have permissions to write. BUT, this is still not a good option
- directly linking binaries to an internal wxpython library just doesn't
sound right. Aren't Python binary extensions something that are normally
loaded by python extension code?
Replying to [comment:3 kyngchaos]:
> Same problem here on OSX. At least on OSX I can directly link in the
_gdi_.so binary with a full path. Or you can create the symlink in some
place you have permissions to write. BUT, this is still not a good option
- directly linking binaries to an internal wxpython library just doesn't
sound right. Aren't Python binary extensions something that are normally
loaded by python extension code?
Right, this solution is unacceptable, for now just a temporal one. I am
trying to find better solution, to avoid replacing wxPseudoDC by wxDC in
C++ code since in wxPython code are used methods of PseudoDC (e.g.
!TranslateId() for moving selected objects) which are not available for
wxDC. Suggestions/ideas welcomed. Martin
Well, looks like it's a no-go for OSX. I think it's because on OSX there
is a distinction between dynamic libraries and loadable modules. Dynamic
libraries are loaded by ld and linked during the build (I think some call
this statically linked), loadable modules are loaded by programs (and
other libraries) at runtime and are not linked (or as some would say,
dynamically linked). Dynamic libraries can also be loaded as modules.
Extensions to libraries and programs, such as Python, PHP, Apache, ...,
are built as modules on OSX. So, _gdi_.so can't be linked as a library,
and you get missing symbols errors.
* summary: v.digit fails to build on Gentoo => v.digit relies upon non-
portable hacks
Comment:
Replying to [comment:5 kyngchaos]:
> Extensions to libraries and programs, such as Python, PHP, Apache, ...,
are built as modules on OSX. So, _gdi_.so can't be linked as a library,
and you get missing symbols errors.
In that case, use of wxPseudoDC must be eliminated from the vdigit module.
I got it to build and run on OSX. The key is that _gdi_.so is loaded by
python when wx is imported, so there really is no need to directly link it
into _grass6_wxvdigit.so. To get around the missing symbols then, on OSX
use the "-undefined dynamic_lookup" flag (note: OSX 10.3 and above only),
instead of the "-lgdi" hack.
So, replace "-lgdi" with a configured variable in Platform.make. If there
is an equivalent dynamic_lookup flag for other platforms, that should be
used instead of directly linking _gdi_.so.
See ticket #61 for other notes. (should these tickets be merged?)
I've been getting a lot of questions about compiling vdigit on OSX, so,
until a better make setup is worked out, I added a conditional in the
makefile to apply my OSX-specific EXTRA_LIBS and SHLIB_LD as needed. I
also changed the vdigit extension to .so because that's what is used for
python extensions on OSX, even though the system library exension is dylib
(many other packages also do this on OSX, like Apache and PHP).
I added local copies of pseudodc.cpp and pseudodc.h to trunk (r35446).
Please let me know if it works for you. Then I will backport it to all
active branches. Anyway it's just workaround how to avoid libgdi link.
Should be solved in the future in better way...
Those are definitely not needed for OSX, so they should be conditionally
compiled, even if this is a temporary solution. The current method of
"-bundle -undefined dynamic_lookup" for OSX is the proper way to handle
python extensions in general, which coincidentally takes care of the GDI
problem.
So, a wildcard couldn't be used for SOURCES. Something like:
Replying to [comment:12 kyngchaos]:
> Those are definitely not needed for OSX, so they should be conditionally
compiled, even if this is a temporary solution. The current method of
"-bundle -undefined dynamic_lookup" for OSX is the proper way to handle
python extensions in general, which coincidentally takes care of the GDI
problem.
That's right, but compiling against local copy of pseudodc should work
also on Mac and should be harmless. Just to avoid other platform dependent
conditionalization.
Replying to [comment:11 martinl]:
> I added local copies of pseudodc.cpp and pseudodc.h to trunk (r35446).
Please let me know if it works for you.
It certainly won't work in general, as the Python code (toolbar.py) is
creating a wx.PseduoDC, not the local version. I daresay that it will work
if the local copies happen to exactly match the installed version of
wxPython, but not otherwise.
IOW, any local copy needs to be SWIG'd and used from Python in place of
wx.PseudoDC.
I was looking into this, and got it mostly working, except for the Python-
ised version of GetIdBounds(). For some reason, SWIG insists upon
returning an opaque wrapper for wxRect* rather than a wxRect proxy.
If you can tolerate modifying the code to pass in a new wx.Rect rather
than expecting GetIdBounds to create and return one, then it's basically
working.
> It certainly won't work in general, as the Python code (toolbar.py) is
creating a wx.PseduoDC, not the local version. I daresay that it will work
if the local copies happen to exactly match the installed version of
wxPython, but not otherwise.
>
> IOW, any local copy needs to be SWIG'd and used from Python in place of
wx.PseudoDC.
I've committed this in r35537.
Drawbacks and caveats:
1. I only SWIG'd the methods which were actually being called.
2. I had to bypass the type-checking for wxDC*. The SWIG'd function is a
wrapper which takes a void* instead of a wxDC*, casts it, and passes that
to DrawToDC[Clipped]. If you pass some other pointer, you'll get a
segfault rather than a Python exception. The alternative was to require
that wxPython's .i files were installed, and figure out how to use them
(without them, SWIG doesn't know how to cast e.g. wxClientDC* to wxDC*).
3. DrawToDCClipped() requires a wx.Rect; it won't accept a tuple or list.