[PATCH] Reintroduce pyuno.so wrapper around libpyuno.so

Stephan Bergmann sbergman at redhat.com
Thu Feb 16 07:42:58 PST 2012


...it was cleaned away by a09ce46818fd4d5e08b3af9a478501cd8ef5b4fe "Port PyUno
to support Python 3" but is still needed to make sure libpyuno.so is loaded
RTLD_GLOBAL (Python apparently loads its modules RTLD_LOCAL).  At least with
pre 4.5 GCC this can cause problems with C++ exception handling, see the mail
thread starting at
<http://lists.freedesktop.org/archives/libreoffice/2012-February/025166.html>
"LibO 3.5RC2: terminate called after throwing an instance of
'com::sun::star::registry::InvalidRegistryException'" for details.

(cherry picked from commit 0b1be1ce0e0ac7b34c4b73d53f4bf32ec5df7290)

...plus...

Adapt pyuno.so wrapper to Python 3 support

(cherry picked from commit 1bb0d979b5ac5ed0cd831c6c8c0ab55dc2621eba)
---
 pyuno/source/module/makefile.mk           |   43 +++++++++++------
 pyuno/source/module/pyuno_dlopenwrapper.c |   76 +++++++++++++++++++++--------
 2 files changed, 83 insertions(+), 36 deletions(-)

diff --git a/pyuno/source/module/makefile.mk b/pyuno/source/module/makefile.mk
index f72e1c3..714a120 100644
--- a/pyuno/source/module/makefile.mk
+++ b/pyuno/source/module/makefile.mk
@@ -50,6 +50,9 @@ EXTRA_FRAMEWORK_FLAG=-framework Python
 .ENDIF # .IF "$(EXTRA_CFLAGS)"!=""
 
 .IF "$(GUI)" == "UNX"
+# python expects modules without the lib prefix
+# pyuno.so even on Mac OS X, because it is a python module
+PYUNO_MODULE=$(DLLDEST)$/pyuno.so
 PYUNORC=pyunorc
 .ELSE
 .IF "$(CROSS_COMPILING)" != "YES"
@@ -109,6 +112,7 @@ DEFLIB1NAME=$(TARGET)
 ALLTAR : \
     $(DLLDEST)/uno.py \
     $(DLLDEST)/unohelper.py \
+    $(PYUNO_MODULE) \
     $(MISC)/$(PYUNORC) \
     $(LB)/lib$(TARGET).a
 
@@ -116,17 +120,10 @@ $(LB)/lib$(TARGET).a: $(MISC)/$(TARGET).def
 	$(DLLTOOL) --dllname $(TARGET)$(DLLPOST) --input-def=$(MISC)/$(TARGET).def --kill-at --output-lib=$(LB)/lib$(TARGET).a
 .ELSE
 
-.IF "$(GUI)"!="WNT"
-# For some reason the build breaks on Windows if this is listed in the
-# prerequisite list of ALLTAR, but pyuno.pyd still gets produced. Go
-# figure. But we need it on non-Windows.
-targetdll=$(LB)/$(TARGET)$(DLLPOST)
-.ENDIF
-
 ALLTAR : \
     $(DLLDEST)/uno.py \
     $(DLLDEST)/unohelper.py \
-    $(targetdll) \
+    $(PYUNO_MODULE) \
     $(MISC)/$(PYUNORC)
 .ENDIF
 .ENDIF
@@ -141,6 +138,29 @@ $(MISC)/framework_link :
 	$(COMMAND_ECHO)ln -sf $(SOLARLIBDIR)/OOoPython.framework $(LB)/OOoPython.framework
 	@touch $@
 
+.IF "$(GUI)" == "UNX"
+$(PYUNO_MODULE) : $(SLO)$/pyuno_dlopenwrapper.obj
+.IF "$(OS)" == "LINUX"
+    @echo $(LINK) $(LINKFLAGS) $(LINKFLAGSRUNPATH_OOO) $(LINKFLAGSSHLCUI) -ldl -o $@ $(SLO)$/pyuno_dlopenwrapper.o > $(MISC)$/$(@:b).cmd
+.ELIF "$(OS)" == "SOLARIS"
+    @echo ld -G -ldl -o $@ $(SLO)$/pyuno_dlopenwrapper.o > $(MISC)$/$(@:b).cmd
+.ELIF "$(OS)" == "FREEBSD"
+    @echo ld -shared -o $@ $(SLO)$/pyuno_dlopenwrapper.o > $(MISC)$/$(@:b).cmd
+.ELIF "$(OS)" == "NETBSD"
+    @echo $(LINK) $(LINKFLAGSSHLCUI) -o $@ $(SLO)$/pyuno_dlopenwrapper.o > $(MISC)$/$(@:b).cmd
+.ELIF "$(OS)" == "OPENBSD"
+    @echo ld -shared -o $@ $(SLO)$/pyuno_dlopenwrapper.o > $(MISC)$/$(@:b).cmd
+.ELIF "$(OS)" == "DRAGONFLY"
+    @echo ld -shared -o $@ $(SLO)$/pyuno_dlopenwrapper.o > $(MISC)$/$(@:b).cmd
+.ELIF "$(OS)" == "MACOSX"
+    @echo $(CC) -bundle -ldl -o $@ $(SLO)$/pyuno_dlopenwrapper.o $(EXTRA_LINKFLAGS) $(EXTRA_FRAMEWORK_FLAG) > $(MISC)$/$(@:b).cmd
+.ELSE
+    @echo $(LINK) $(LINKFLAGSSHLCUI) -o $@ $(SLO)$/pyuno_dlopenwrapper.o > $(MISC)$/$(@:b).cmd
+.ENDIF
+    cat $(MISC)$/$(@:b).cmd
+    @+source $(MISC)$/$(@:b).cmd
+.ENDIF
+
 $(MISC)/$(PYUNORC) : pyuno
 	-rm -f $@
 	cat pyuno > $@
@@ -149,11 +169,4 @@ $(MISC)/pyuno.flt : pyuno.flt
 	-rm -f $@
 	cat $? > $@
 
-.IF "$(DLLPRE)"!=""
-# python does not accept the "lib" prefix in the module library
-$(LB)/$(TARGET)$(DLLPOST) : $(LB)/$(DLLPRE)$(TARGET)$(DLLPOST)
-	-rm -f $@
-	ln -s $? $@
-.ENDIF
-
 .ENDIF # L10N_framework
diff --git a/pyuno/source/module/pyuno_dlopenwrapper.c b/pyuno/source/module/pyuno_dlopenwrapper.c
index 1ace044..487665b 100644
--- a/pyuno/source/module/pyuno_dlopenwrapper.c
+++ b/pyuno/source/module/pyuno_dlopenwrapper.c
@@ -26,38 +26,73 @@
  *
  ************************************************************************/
 
-#include <rtl/string.h>
+#include "sal/config.h"
 
 #include <stdlib.h>
 #include <string.h>
 
-#ifdef LINUX
-#  ifndef __USE_GNU
-#  define __USE_GNU
-#  endif
+#if defined LINUX && !defined __USE_GNU
+#define __USE_GNU
 #endif
 #include <dlfcn.h>
 
-void initpyuno ()
-{
-    Dl_info dl_info;
-    void (*func)(void);
+#include "Python.h"
+
+#include "rtl/string.h"
 
-    if (dladdr((void*)&initpyuno, &dl_info) != 0) {
-        void* h = 0;
-    size_t len = strrchr(dl_info.dli_fname, '/') - dl_info.dli_fname + 1;
-    char* libname = malloc(len + RTL_CONSTASCII_LENGTH( SAL_DLLPREFIX "pyuno" SAL_DLLEXTENSION ) + 1);
-        strncpy(libname, dl_info.dli_fname, len);
-        strcpy(libname + (len), SAL_DLLPREFIX "pyuno" SAL_DLLEXTENSION);
+/* A wrapper around libpyuno.so, making sure the latter is loaded RTLD_GLOBAL
+   so that C++ exception handling works with old GCC versions (that determine
+   RTTI identity by comparing string addresses rather than string content).
+*/
 
-        h = dlopen (libname, RTLD_NOW | RTLD_GLOBAL);
+static void * load(void * address, char const * symbol) {
+    Dl_info dl_info;
+    char * slash;
+    size_t len;
+    char * libname;
+    void * h;
+    void * func;
+    if (dladdr(address, &dl_info) == 0) {
+        abort();
+    }
+    slash = strrchr(dl_info.dli_fname, '/');
+    if (slash == NULL) {
+        abort();
+    }
+    len = slash - dl_info.dli_fname + 1;
+    libname = malloc(
+        len + RTL_CONSTASCII_LENGTH(SAL_DLLPREFIX "pyuno" SAL_DLLEXTENSION)
+        + 1);
+    if (libname == 0) {
+        abort();
+    }
+    strncpy(libname, dl_info.dli_fname, len);
+    strcpy(libname + len, SAL_DLLPREFIX "pyuno" SAL_DLLEXTENSION);
+    h = dlopen(libname, RTLD_NOW | RTLD_GLOBAL);
     free(libname);
-        if( h )
-        {
-            func = (void (*)())dlsym (h, "initpyuno");
-            (func) ();
-        }
+    if (h == NULL) {
+        abort();
     }
+    func = dlsym(h, symbol);
+    if (func == NULL) {
+        abort();
+    }
+    return func;
 }
 
+#if PY_MAJOR_VERSION >= 3
+
+PyObject * PyInit_pyuno(void) {
+    return
+        ((PyObject * (*)(void)) load((void *) &PyInit_pyuno, "PyInit_pyuno"))();
+}
+
+#else
+
+void initpyuno(void) {
+    ((void (*)(void)) load((void *) &initpyuno, "initpyuno"))();
+}
+
+#endif
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
-- 
1.7.7.6


--------------020209080105050403010707--


More information about the LibreOffice mailing list