So here's a re-work that should allow for dynamic loading on platforms
other than Solaris.  The autoconf bits are tuned for Solaris, but change
-Kpic to -fpic, -G to -shared, and SunOS to Linux, and I think it might
work, or at least come close.

The difference here is that if_python.c itself is converted into a shared
object which can be loaded by vim.  That way, if_python.so can link simply
against python and not have to worry about the mess of dlsym calls, lazy
loading, etc, that you needed in the main program in my first attempt.
Then vim either loads or fails to load if_python.so.

New patch is attached.

Thanks,
Danek

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

--- Makefile.orig       Sat Aug  9 07:50:04 2008
+++ Makefile    Mon Feb 16 01:07:36 2009
@@ -966,6 +966,8 @@
 PRINTSUBLOC    = $(VIMRTLOC)$(PRINTSUBDIR)
 SCRIPTLOC      = $(VIMRTLOC)
 
+VIMSOLOC       = $(LIBDIR)$(VIMRTDIR)
+
 ### Only set VIMRUNTIMEDIR when VIMRTLOC is set to a different location and
 ### the runtime directory is not below it.
 #VIMRUNTIMEDIR = $(VIMRTLOC)
@@ -1334,6 +1336,7 @@
 DEST_SCRIPT = $(DESTDIR)$(SCRIPTLOC)
 DEST_PRINT = $(DESTDIR)$(PRINTSUBLOC)
 DEST_MAN_TOP = $(DESTDIR)$(MANDIR)
+DEST_SO = $(DESTDIR)$(VIMSOLOC)
 
 # We assume that the ".../man/xx/man1/" directory is for latin1 manual pages.
 # Some systems use UTF-8, but these should find the ".../man/xx.UTF-8/man1/"
@@ -1555,7 +1558,7 @@
        os_mswin.pro os_beos.pro os_vms.pro os_riscos.pro $(PERL_PRO)
 
 # Default target is making the executable and tools
-all: $(VIMTARGET) $(TOOLS) languages $(GUI_BUNDLE)
+all: $(VIMTARGET) $(PYTHON_SO) $(TOOLS) languages $(GUI_BUNDLE)
 
 tools: $(TOOLS)
 
@@ -1761,7 +1764,7 @@
 
 install_gui_extra: installgtutorbin
 
-installvim: installvimbin installtutorbin \
+installvim: installvimbin installvimso installtutorbin \
                installruntime installlinks installmanlinks
 
 #
@@ -1784,6 +1787,11 @@
 # may create a link to the new executable from /usr/bin/vi
        -$(LINKIT)
 
+installvimso: $(PYTHON_SO) $(DESTDIR)$(libdir) $(DEST_SO)
+       -$(INSTALL_PROG) $(PYTHON_SO) $(DEST_SO)
+       -$(STRIP) $(DEST_SO)/$(PYTHON_SO)
+       -chmod $(BINMOD) $(DEST_SO)/$(PYTHON_SO)
+
 # Long list of arguments for the shell script that installs the manual pages
 # for one language.
 INSTALLMANARGS = $(VIMLOC) $(SCRIPTLOC) $(VIMRCLOC) $(HELPSOURCE) $(MANMOD) \
@@ -2020,7 +2028,7 @@
        @echo You need to unpack the runtime archive before running "make 
install".
        test -f error
 
-$(DESTDIR)$(exec_prefix) $(DEST_BIN) \
+$(DESTDIR)$(exec_prefix) $(DEST_BIN) $(DEST_SO) \
                $(DEST_VIM) $(DEST_RT) $(DEST_HELP) \
                $(DEST_PRINT) $(DEST_COL) $(DEST_SYN) $(DEST_IND) $(DEST_FTP) \
                $(DEST_LANG) $(DEST_KMAP) $(DEST_COMP) \
@@ -2184,6 +2192,7 @@
 # We support common typing mistakes for Juergen! :-)
 clean celan: testclean
        -rm -f *.o objects/* core $(VIMTARGET).core $(VIMTARGET) vim xxd/*.o
+       -rm -f $(PYTHON_SO)
        -rm -f $(TOOLS) auto/osdef.h auto/pathdef.c auto/if_perl.c
        -rm -f conftest* *~ auto/link.sed
        -rm -rf $(APPDIR)
@@ -2429,9 +2438,15 @@
 objects/if_perlsfio.o: if_perlsfio.c
        $(CCC) -o $@ if_perlsfio.c
 
+objects/if_python_stub.o: if_python_stub.c
+       $(CCC) -o $@ if_python_stub.c
+
 objects/if_python.o: if_python.c
-       $(CCC) -o $@ if_python.c
+       $(CCC) $(PYTHON_SO_CFLAGS) -o $@ if_python.c
 
+$(PYTHON_SO): $(PYTHON_SO_OBJ)
+       $(CClink) $(PYTHON_SO_LIBS) -o $@ $(PYTHON_SO_OBJ)
+
 objects/if_ruby.o: if_ruby.c
        $(CCC) -o $@ if_ruby.c
 
@@ -2503,7 +2518,7 @@
 
 objects/py_config.o: $(PYTHON_CONFDIR)/config.c
        $(CCC) -o $@ $(PYTHON_CONFDIR)/config.c \
-               -I$(PYTHON_CONFDIR) -DHAVE_CONFIG_H -DNO_MAIN
+               $(PYTHON_INC) -I$(PYTHON_CONFDIR) -DHAVE_CONFIG_H -DNO_MAIN
 
 objects/py_getpath.o: $(PYTHON_CONFDIR)/getpath.c
        $(CCC) -o $@ $(PYTHON_CONFDIR)/getpath.c \
--- config.mk.in.orig   Sat Jun 21 08:56:41 2008
+++ config.mk.in        Mon Feb 16 00:54:57 2009
@@ -55,6 +55,11 @@
 PYTHON_OBJ     = @PYTHON_OBJ@
 PYTHON_CFLAGS  = @PYTHON_CFLAGS@
 PYTHON_LIBS    = @PYTHON_LIBS@
+PYTHON_INC     = @PYTHON_INC@
+PYTHON_SO      = @PYTHON_SO@
+PYTHON_SO_OBJ  = @PYTHON_SO_OBJ@
+PYTHON_SO_CFLAGS       = @PYTHON_SO_CFLAGS@
+PYTHON_SO_LIBS = @PYTHON_SO_LIBS@
 PYTHON_CONFDIR = @PYTHON_CONFDIR@
 PYTHON_GETPATH_CFLAGS = @PYTHON_GETPATH_CFLAGS@
 
@@ -112,6 +117,9 @@
 ### For autoconf 2.60 and later (avoid a warning)
 datarootdir    = @datarootdir@
 
+### Prefix for location of native-code plugins
+LIBDIR         = @libdir@
+
 ### Prefix for location of data files
 DATADIR                = @datadir@
 
--- configure.in.orig   Sat Feb 14 13:53:40 2009
+++ configure.in        Mon Feb 16 00:58:47 2009
@@ -608,10 +608,10 @@
 
 AC_MSG_CHECKING(--enable-pythoninterp argument)
 AC_ARG_ENABLE(pythoninterp,
-       [  --enable-pythoninterp   Include Python interpreter.], ,
+       [  --enable-pythoninterp[=OPTS] Include Python interpreter. 
[OPTS=yes/no/dynamic]], ,
        [enable_pythoninterp="no"])
 AC_MSG_RESULT($enable_pythoninterp)
-if test "$enable_pythoninterp" = "yes"; then
+if test "$enable_pythoninterp" = "yes" -o "$enable_pythoninterp" = "dynamic"; 
then
   dnl -- find the python executable
   AC_PATH_PROG(vi_cv_path_python, python)
   if test "X$vi_cv_path_python" != "X"; then
@@ -668,6 +668,12 @@
        done
       ])
 
+      if test "${enable_pythoninterp}" = "dynamic"; then
+       if test "`(uname) 2>/dev/null`" != SunOS; then
+         AC_MSG_RESULT([dynamically loaded Python interpreter not supported!])
+       fi
+      fi
+
       PYTHON_CONFDIR="${vi_cv_path_python_conf}"
 
       if test "X$PYTHON_CONFDIR" = "X"; then
@@ -697,7 +703,12 @@
              if test "${vi_cv_var_python_version}" = "1.4"; then
                  vi_cv_path_python_plibs="${PYTHON_CONFDIR}/libModules.a 
${PYTHON_CONFDIR}/libPython.a ${PYTHON_CONFDIR}/libObjects.a 
${PYTHON_CONFDIR}/libParser.a"
              else
+               if test "${enable_pythoninterp}" = "dynamic"; then
+                 vi_cv_path_python_plibs=""
+                 vi_cv_path_python_psolibs="-G -L${PYTHON_CONFDIR} -zignore 
-lpython${vi_cv_var_python_version}"
+               else
                  vi_cv_path_python_plibs="-L${PYTHON_CONFDIR} 
-lpython${vi_cv_var_python_version}"
+               fi
              fi
              vi_cv_path_python_plibs="${vi_cv_path_python_plibs} 
${python_MODLIBS} ${python_LIBS} ${python_SYSLIBS} ${python_LINKFORSHARED}"
              dnl remove -ltermcap, it can conflict with an earlier -lncurses
@@ -707,16 +718,30 @@
 
        PYTHON_LIBS="${vi_cv_path_python_plibs}"
        if test "${vi_cv_path_python_pfx}" = "${vi_cv_path_python_epfx}"; then
-         
PYTHON_CFLAGS="-I${vi_cv_path_python_pfx}/include/python${vi_cv_var_python_version}"
+         
PYTHON_INC="-I${vi_cv_path_python_pfx}/include/python${vi_cv_var_python_version}"
        else
-         
PYTHON_CFLAGS="-I${vi_cv_path_python_pfx}/include/python${vi_cv_var_python_version}
 -I${vi_cv_path_python_epfx}/include/python${vi_cv_var_python_version}"
+         
PYTHON_INC="-I${vi_cv_path_python_pfx}/include/python${vi_cv_var_python_version}
 -I${vi_cv_path_python_epfx}/include/python${vi_cv_var_python_version}"
        fi
+       if test "${enable_pythoninterp}" = "dynamic"; then
+         PYTHON_LIBS="${PYTHON_LIBS} -R\$(VIMSOLOC)"
+         PYTHON_CFLAGS="-DDYNAMIC_PYTHON"
+         PYTHON_SO_CFLAGS="${PYTHON_INC} -Kpic"
+         PYTHON_SO_LIBS="${vi_cv_path_python_psolibs}"
+         PYTHON_SO="if_python.so"
+       else
+         PYTHON_CFLAGS="${PYTHON_INC}"
+       fi
        PYTHON_SRC="if_python.c"
        dnl For Mac OSX 10.2 config.o is included in the Python library.
        if test "x$MACOSX" = "xyes"; then
          PYTHON_OBJ="objects/if_python.o"
        else
-         PYTHON_OBJ="objects/if_python.o objects/py_config.o"
+         if test "${enable_pythoninterp}" = "dynamic"; then
+           PYTHON_OBJ="objects/if_python_stub.o"
+           PYTHON_SO_OBJ="objects/if_python.o objects/py_config.o"
+         else
+           PYTHON_OBJ="objects/if_python_stub.o objects/if_python.o 
objects/py_config.o"
+         fi
        fi
        if test "${vi_cv_var_python_version}" = "1.4"; then
           PYTHON_OBJ="$PYTHON_OBJ objects/py_getpath.o"
@@ -775,6 +800,11 @@
          PYTHON_OBJ=
          PYTHON_LIBS=
          PYTHON_CFLAGS=
+         PYTHON_INC=
+         PYTHON_SO=
+         PYTHON_SO_OBJ=
+         PYTHON_SO_CFLAGS=
+         PYTHON_SO_LIBS=
        fi
 
       fi
@@ -789,6 +819,11 @@
 AC_SUBST(PYTHON_CFLAGS)
 AC_SUBST(PYTHON_SRC)
 AC_SUBST(PYTHON_OBJ)
+AC_SUBST(PYTHON_INC)
+AC_SUBST(PYTHON_SO)
+AC_SUBST(PYTHON_SO_OBJ)
+AC_SUBST(PYTHON_SO_CFLAGS)
+AC_SUBST(PYTHON_SO_LIBS)
 
 AC_MSG_CHECKING(--enable-tclinterp argument)
 AC_ARG_ENABLE(tclinterp,
--- if_python.c.orig    Sat Feb 14 13:53:41 2009
+++ if_python.c Mon Feb 16 00:42:21 2009
@@ -85,7 +85,7 @@
 # define PY_CAN_RECURSE
 #endif
 
-#if defined(DYNAMIC_PYTHON) || defined(PROTO)
+#if (defined(DYNAMIC_PYTHON) && defined(MSWIN)) || defined(PROTO)
 # ifndef DYNAMIC_PYTHON
 #  define HINSTANCE long_u             /* for generating prototypes */
 # endif
@@ -387,7 +387,7 @@
  * Internal function prototypes.
  */
 
-static void DoPythonCommand(exarg_T *, const char *);
+void DoPythonCommand(exarg_T *, const char *);
 static PyInt RangeStart;
 static PyInt RangeEnd;
 
@@ -482,7 +482,7 @@
 
     ++recurse;
 
-#ifdef DYNAMIC_PYTHON
+#if defined(DYNAMIC_PYTHON) && defined(MSWIN)
     if (hinstPython && Py_IsInitialized())
     {
        Python_RestoreThread();     /* enter python */
@@ -521,7 +521,7 @@
        /* initialise threads */
        PyEval_InitThreads();
 
-#ifdef DYNAMIC_PYTHON
+#if defined(DYNAMIC_PYTHON) && defined(MSWIN)
        get_exceptions();
 #endif
 
@@ -558,7 +558,7 @@
 /*
  * External interface
  */
-    static void
+    void
 DoPythonCommand(exarg_T *eap, const char *cmd)
 {
 #ifndef PY_CAN_RECURSE
@@ -633,69 +633,6 @@
     return;        /* keeps lint happy */
 }
 
-/*
- * ":python"
- */
-    void
-ex_python(exarg_T *eap)
-{
-    char_u *script;
-
-    script = script_get(eap, eap->arg);
-    if (!eap->skip)
-    {
-       if (script == NULL)
-           DoPythonCommand(eap, (char *)eap->arg);
-       else
-           DoPythonCommand(eap, (char *)script);
-    }
-    vim_free(script);
-}
-
-#define BUFFER_SIZE 1024
-
-/*
- * ":pyfile"
- */
-    void
-ex_pyfile(exarg_T *eap)
-{
-    static char buffer[BUFFER_SIZE];
-    const char *file = (char *)eap->arg;
-    char *p;
-
-    /* Have to do it like this. PyRun_SimpleFile requires you to pass a
-     * stdio file pointer, but Vim and the Python DLL are compiled with
-     * different options under Windows, meaning that stdio pointers aren't
-     * compatible between the two. Yuk.
-     *
-     * Put the string "execfile('file')" into buffer. But, we need to
-     * escape any backslashes or single quotes in the file name, so that
-     * Python won't mangle the file name.
-     */
-    strcpy(buffer, "execfile('");
-    p = buffer + 10; /* size of "execfile('" */
-
-    while (*file && p < buffer + (BUFFER_SIZE - 3))
-    {
-       if (*file == '\\' || *file == '\'')
-           *p++ = '\\';
-       *p++ = *file++;
-    }
-
-    /* If we didn't finish the file name, we hit a buffer overflow */
-    if (*file != '\0')
-       return;
-
-    /* Put in the terminating "')" and a null */
-    *p++ = '\'';
-    *p++ = ')';
-    *p++ = '\0';
-
-    /* Execute the file */
-    DoPythonCommand(eap, buffer);
-}
-
 /******************************************************
  * 2. Python output stream: writes output via [e]msg().
  */
--- if_python_stub.c.orig       Mon Feb 16 00:34:57 2009
+++ if_python_stub.c    Mon Feb 16 00:42:23 2009
@@ -1,0 +1,126 @@
+/* vi:set ts=8 sts=4 sw=4: */
+#include "vim.h"
+
+#ifdef DYNAMIC_PYTHON
+#include <dlfcn.h>
+
+static void *if_python_handle;
+
+static void DoPythonCommand(exarg_T *eap, const char *cmd) {
+    (*(void (*)(exarg_T *, const char *))dlsym(if_python_handle, 
"DoPythonCommand"))(eap, cmd);
+}
+void python_window_free(win_T *win) {
+    (*(void (*)(win_T *))dlsym(if_python_handle, "python_window_free"))(win);
+}
+void python_buffer_free(buf_T *buf) {
+    (*(void (*)(buf_T *))dlsym(if_python_handle, "python_buffer_free"))(buf);
+}
+void python_end(void) {
+    if (if_python_handle) {
+       (*(void (*)(void))dlsym(if_python_handle, "python_end"))();
+       dlclose(if_python_handle);
+       if_python_handle = NULL;
+    }
+}
+#else
+void DoPythonCommand(exarg_T *, const char *);
+#endif
+
+    static int
+load_python(int verbose)
+{
+#ifdef DYNAMIC_PYTHON
+    if (if_python_handle)
+       return OK;
+
+    if_python_handle = dlopen("if_python.so", RTLD_NOW);
+    if (!if_python_handle)
+    {
+       EMSG2(_(e_loadlib), "if_python.so");
+       return FAIL;
+    }
+#endif
+
+    return OK;
+}
+
+    int
+python_enabled(int verbose)
+{
+    return load_python(verbose) == OK;
+}
+
+/*
+ * ":python"
+ */
+    void
+ex_python(exarg_T *eap)
+{
+    char_u *script;
+
+    if (!load_python(TRUE))
+    {
+       EMSG(_("E263: Sorry, this command is disabled, the Python library could 
not be loaded."));
+       return;
+    }
+
+    script = script_get(eap, eap->arg);
+    if (!eap->skip)
+    {
+       if (script == NULL)
+           DoPythonCommand(eap, (char *)eap->arg);
+       else
+           DoPythonCommand(eap, (char *)script);
+    }
+    vim_free(script);
+}
+
+#define BUFFER_SIZE 1024
+
+/*
+ * ":pyfile"
+ */
+    void
+ex_pyfile(exarg_T *eap)
+{
+    static char buffer[BUFFER_SIZE];
+    const char *file = (char *)eap->arg;
+    char *p;
+
+    if (!python_enabled(TRUE))
+    {
+       EMSG(_("E263: Sorry, this command is disabled, the Python library could 
not be loaded."));
+       return;
+    }
+
+    /* Have to do it like this. PyRun_SimpleFile requires you to pass a
+     * stdio file pointer, but Vim and the Python DLL are compiled with
+     * different options under Windows, meaning that stdio pointers aren't
+     * compatible between the two. Yuk.
+     *
+     * Put the string "execfile('file')" into buffer. But, we need to
+     * escape any backslashes or single quotes in the file name, so that
+     * Python won't mangle the file name.
+     */
+    strcpy(buffer, "execfile('");
+    p = buffer + 10; /* size of "execfile('" */
+
+    while (*file && p < buffer + (BUFFER_SIZE - 3))
+    {
+       if (*file == '\\' || *file == '\'')
+           *p++ = '\\';
+       *p++ = *file++;
+    }
+
+    /* If we didn't finish the file name, we hit a buffer overflow */
+    if (*file != '\0')
+       return;
+
+    /* Put in the terminating "')" and a null */
+    *p++ = '\'';
+    *p++ = ')';
+    *p++ = '\0';
+
+    /* Execute the file */
+    DoPythonCommand(eap, buffer);
+}

Raspunde prin e-mail lui