Ilya Zakharevich on Sat, 04 May 2019 14:06:35 +0200


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: PATCH: support install() on Win: [Re: Please test pari-2.11.2 prerelease 1]


On Fri, May 03, 2019 at 11:41:39AM +0200, Bill Allombert wrote:
> > I attach a patch to es.c.  Additionally, a def file should be linked
> > to the exe.  The patch below shows one way to do it.  (I do not know
> > how to modify the build environment to make this change to Makefile.)
> 
> This is done in config/Makefile.SH

Cannot REALLY test this on Windows!  (See my other reports.) 

> > --- pari-2.11.1/src/language/es.c-pre	2018-07-25 11:00:21.000000000 -0700
> > +++ pari-2.11.1/src/language/es.c	2019-05-02 03:25:45.470881300 -0700
> > @@ -5200,7 +5200,6 @@ install0(const char *name, const char *l
> >  #  define RTLD_GLOBAL 0
> >  #endif
> >    handle = gp_dlopen(lib, RTLD_LAZY|RTLD_GLOBAL);
> > -
> >    if (!handle)
> >    {
> >      const char *s = dlerror(); if (s) err_printf("%s\n\n",s);
> > @@ -5236,12 +5235,24 @@ gp_LoadLibrary(const char *name)
> >    }
> >    return NULL;
> >  }
> > +static int I_m_a_DLL = -1;
> > +static HMODULE hmod_exe, hmod_dll;
> >  static void *
> >  install0(const char *name, const char *lib)
> >  {
> >    HMODULE handle;
> >  
> > -  handle = gp_LoadLibrary(lib);
> > +  if (lib == pari_library_path) {
> > +    if (I_m_a_DLL < 0) {
> > +      hmod_exe = hmod_dll = GetModuleHandleA(NULL);
> > +      if (!hmod_exe	/* Can this happen? */
> > +          || !(GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
> > +          		          (LPCSTR)install0, &hmod_dll)))
> > +        I_m_a_DLL = hmod_exe != hmod_dll;
> > +    }
> > +    handle = hmod_dll;
> > +  } else
> > +    handle = gp_LoadLibrary(lib);
> >    if (!handle)
> >    {
> >      if (lib) pari_err(e_MISC,"couldn't open dynamic library '%s'",lib);
> 
> What does that do ?

Sorry, I thought that this is self-explanatory.  To load a function,
you need a handle to a loaded ???image??? (DLL or EXE).  The ???old??? code
hardwires the name of the PARI DLL.  This cannot work (neither on
Unix, nor on Windows;?????????but I do not know how to fix it on Unix). 

There are 3 typical cases:

a) "addii" is in the EXE file (such as a static build of GP).
b) "addii" is in the libPARI.DLL (such as something dynamically linked
   with libPARI).
c) "addii" is in a DLL statically linked with libPARI (such as in
   Math::Pari DLL?????????which is by default statically linked with [a
   custom build of] libPARI).

The ???old??? implementation supports only the case ???b???.

However, in all these cases, "addii" is in the same ???image??? as
"install0".  So we use GetModuleHandleExA() to find the handle of the
???image??? which contains the function install0().  Then all one needs to
support cases ???a??? and ???c??? is the corresponding executables with the
export list.

The above patch to Makefile links GP-STA.EXE with such a file.  This
finishes support of the case ???a???.  To support ???c???, one needs to link
the DLL in question with a suitable .def file (not YOUR worries ;-).

> Does 
> install("addii",GG);
> addii(2,3)
> work with this patch with gp-sta ?

Of course.  And with gp-dyn.  (This is why I needed to build it.)

Hope this helps,
Ilya

P.S.  The code above also distinguishes between ???in an exe??? and ???in a
      dll??? (at runtime!).  ???Just in case???, the answer is stored in the
      variable I_m_a_DLL (but the particular value is not used?????????we
      only check whether it is initialized.  I *believe* the answer
      may be useful in some future time?????????but currently do not know
      where. ;-)