Thread: Building Windows Server Extensions Using VC++ 2005

Building Windows Server Extensions Using VC++ 2005

From
Charlie Savage
Date:
Hmm...this didn't seem to make it to the newsgroup.  Apologies if its a 
repeat.

Charlie

-------------
Hi everyone,

I've been able to successfully build server extension using Visual
Studio 2005 for Windows Postgresql 8.1.  However, it took a few tweaks
which I thought I should document (maybe these issues could be fixed in
future postgresql versions?):


1.  There is no lib file for VC++ to link against.  This can be created
easily enough by going to src/backend directory and running:

lib /MACHINE:x86 /NAME:postgres.exe /DEF:postgres.def

Note the use of /NAME to tell VC++ it is linking against an executable
and not a dll.

It would be nice if this lib file was automatically installed on windows
when installing postgresql.


2.  Requirement on strings.h

In c.h:69 there is this code:

#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif


In pg_config.h:405 this is defined:

/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1

However, Visual Studio 2005 does not include this file.  For a
workaround I simply added it but that's a bit of hack.


3.  This is a bigger issue, and took a while to figure out. If you try
to use the Version 1 calling convention, your function will be called
but if you try to do anything with the passed in parameters a
segmentation fault will occur.  If you use the Version 0 calling
convention things work fine.

The problem is if you use PG_FUNCTION_INFO_V1 postgres does not see the
generated function because it is not exported from the dll and thus
assumes the Version 0 calling convention when in fact your function is
using Version1.  The problem is in fmgr.h:298

#define PG_FUNCTION_INFO_V1(funcname) \

extern  Pg_finfo_record * CppConcat(pg_finfo_,funcname) (void); \
...

For windows to export this function it must be:

extern __declspec(dllexport) Pg_finfo_record *
CppConcat(pg_finfo_,funcname) (void);

Would it be possible to add a DLLEXPORT macro here to fix this?


4.  Last, and the biggest issue, if my function calls pfree it blows up. What is happening is that pfree somehow ends
uppointing to a random
 
spot in memory - thus when you try to call it you execute invalid code
(in fact you never execute pfree at all as far as I can see).  I worked
around this by using pgport_pfree which does work.  Haven't a clue why...


Here is the assembly for successfully calling pgport_pfree:

pgport_pfree(fileName);
100112D3  mov         eax,dword ptr [ebp-0Ch]
100112D6  push        eax  100112D7  call        100110C3
100112DC  add         esp,4

100110C3  jmp         1001131A

pgport_pfree:
1001131A  jmp         dword ptr ds:[10016288h]

005CF140  push        ebp  005CF141  mov         ebp,esp
005CF143  sub         esp,8
005CF146  mov         eax,dword ptr [ebp+8]
005CF149  mov         dword ptr [esp+4],eax
005CF14D  mov         eax,dword ptr ds:[006A9F94h]
005CF152  mov         dword ptr [esp],eax
005CF155  call        005CF0D0
005CF15A  leave            005CF15B  ret

And here is pfree.  Note at the end the code tries to execute "db" at
005E1560 causing a segmentation fault.

pfree( fileName );
100112D3  mov         eax,dword ptr [ebp-0Ch]
100112D6  push        eax  100112D7  call        1001110E
100112DC  add         esp,4

1001110E  jmp         10011238

pfree:
10011238  jmp         dword ptr ds:[1001628Ch]

005E1560  db          ffh

Hope this helps others.  It would be great if building postgresql server
extensions with VC++ worked out of the box on Windows (in addition of
course to using MingW) since I think it would open up a wider audience.

Charlie


Re: Building Windows Server Extensions Using VC++ 2005

From
"Qingqing Zhou"
Date:
"Charlie Savage" <cfis@interserv.com> wrote
>
> I've been able to successfully build server extension using Visual
> Studio 2005 for Windows Postgresql 8.1.  However, it took a few tweaks
> which I thought I should document (maybe these issues could be fixed in
> future postgresql versions?):
>
>

Is this one related?

http://pgfoundry.org/projects/vcproject/

Regards,
Qingqing 




Re: Building Windows Server Extensions Using VC++ 2005

From
Charlie Savage
Date:
Not really.  This is for building VC++ extensions that work with 
Postgresql for Windows, which is built using MinGW.  Thus it allows you 
to build extensions with VC++ that work with Postgresql "out-of-the-box" 
on the Windows platform.

In contrast, the link below is for rebuilding Postgresql itself, but 
with VC++ instead of MinGW.

Charlie

Qingqing Zhou wrote:
> "Charlie Savage" <cfis@interserv.com> wrote
>> I've been able to successfully build server extension using Visual
>> Studio 2005 for Windows Postgresql 8.1.  However, it took a few tweaks
>> which I thought I should document (maybe these issues could be fixed in
>> future postgresql versions?):
>>
>>
> 
> Is this one related?
> 
> http://pgfoundry.org/projects/vcproject/
> 
> Regards,
> Qingqing 
> 
> 


Re: Building Windows Server Extensions Using VC++ 2005

From
"Magnus Hagander"
Date:
> > In pg_config.h:405 this is defined:
> >
> > /* Define to 1 if you have the <strings.h> header file. */ #define
> > HAVE_STRINGS_H 1
> >
> > However, Visual Studio 2005 does not include this file.  For a
> > workaround I simply added it but that's a bit of hack.
>
> Ah, so even though you are using MSVC, you are using the
> config file from MinGW.  Easy fix, included in the patch
> below, and applied for 8.2.

Um, is WIN32_CLIENT_ONLY really defined when you're building a backend
extension? That seems wrong.

The whole problem seems to be the using of the pg_config.h from mingw
when building with msvc. Why not just use the correct pg_config.h in the
first place? What happens then?


IIRC, there were other problems building extensions with MSVC - such as
struct alignment and stuff. Not sure if that has been taken care of? If
not, there really isn't much point in fixing the headers alone :-)

//Magnus


Re: Building Windows Server Extensions Using VC++ 2005

From
Bruce Momjian
Date:
Magnus Hagander wrote:
> > > In pg_config.h:405 this is defined:
> > > 
> > > /* Define to 1 if you have the <strings.h> header file. */ #define 
> > > HAVE_STRINGS_H 1
> > > 
> > > However, Visual Studio 2005 does not include this file.  For a 
> > > workaround I simply added it but that's a bit of hack.
> > 
> > Ah, so even though you are using MSVC, you are using the 
> > config file from MinGW.  Easy fix, included in the patch 
> > below, and applied for 8.2.
> 
> Um, is WIN32_CLIENT_ONLY really defined when you're building a backend
> extension? That seems wrong.

Well, it is defined:
#if defined(_MSC_VER) || defined(__BORLANDC__)#define WIN32_CLIENT_ONLY#endif

> The whole problem seems to be the using of the pg_config.h from mingw
> when building with msvc. Why not just use the correct pg_config.h in the
> first place? What happens then?

We can't generate a pg_config.h for WIN32_CLIENT_ONLY because there is
no shell build environment.

> IIRC, there were other problems building extensions with MSVC - such as
> struct alignment and stuff. Not sure if that has been taken care of? If
> not, there really isn't much point in fixing the headers alone :-)

Well, I figure alignment would be based on the CPU, not the compiler,
but I might be wrong.

I added the capability, and why it was added, so if we decide the idea
is a failure, we know what to remove.

--  Bruce Momjian   http://candle.pha.pa.us SRA OSS, Inc.   http://www.sraoss.com
 + If your life is a hard drive, Christ can be your backup. +


Re: Building Windows Server Extensions Using VC++ 2005

From
"Magnus Hagander"
Date:
> > Um, is WIN32_CLIENT_ONLY really defined when you're
> building a backend
> > extension? That seems wrong.
>
> Well, it is defined:
>
>     #if defined(_MSC_VER) || defined(__BORLANDC__)
>     #define WIN32_CLIENT_ONLY
>     #endif

Oops. I obviously forgot all about that :-)


> > The whole problem seems to be the using of the pg_config.h
> from mingw
> > when building with msvc. Why not just use the correct
> pg_config.h in
> > the first place? What happens then?
>
> We can't generate a pg_config.h for WIN32_CLIENT_ONLY because
> there is no shell build environment.

Right. But we have include/pg_config.h.win32 which is supposed to be
used in this case. The win32 native build of the backend will copy that
file into pg_config.h.

The problem here is that the backend is built with mingw but the
extension with msvc. If you'd start from fresh, there would be no
pg_config.h to include. The pg_config.h.win32 file is supposed to be
preset for the MSVC environment (which is the same as borland on win32,
but different from mingw).


> > IIRC, there were other problems building extensions with
> MSVC - such
> > as struct alignment and stuff. Not sure if that has been taken care
> > of? If not, there really isn't much point in fixing the
> headers alone
> > :-)
>
> Well, I figure alignment would be based on the CPU, not the
> compiler, but I might be wrong.

Um. struct packing? I don't remember exactly what it was, but IIRC it
was something.


> I added the capability, and why it was added, so if we decide
> the idea is a failure, we know what to remove.

Right. I've never tried using msvc for a server extension, and the
general answer has always been "don't do it". But it may well have
changed now.


//Magnus


Re: Building Windows Server Extensions Using VC++ 2005

From
Tom Lane
Date:
"Magnus Hagander" <mha@sollentuna.net> writes:
> The problem here is that the backend is built with mingw but the
> extension with msvc.

I don't think that it's very reasonable to expect that to work.
The two compilers very likely have different rules for struct
packing, to take just the first gotcha.  Maybe they are compatible
enough that it will work, but if it does not we cannot fix it.
        regards, tom lane


Re: Building Windows Server Extensions Using VC++ 2005

From
Greg Stark
Date:
Tom Lane <tgl@sss.pgh.pa.us> writes:

> "Magnus Hagander" <mha@sollentuna.net> writes:
> > The problem here is that the backend is built with mingw but the
> > extension with msvc.
> 
> I don't think that it's very reasonable to expect that to work.
> The two compilers very likely have different rules for struct
> packing, to take just the first gotcha.  Maybe they are compatible
> enough that it will work, but if it does not we cannot fix it.

Well that sort of stuff is supposed to be covered by the ABI. Consider that if
it didn't then you wouldn't be able to use any of the standard libraries
without recompiling them for each compiler since a number of standard library
APIs depend on structs like timeval or stat.

I'm not saying there aren't risks, but in theory it's supposed to work.

-- 
greg



Re: Building Windows Server Extensions Using VC++ 2005

From
Tom Lane
Date:
Greg Stark <gsstark@mit.edu> writes:
> Well that sort of stuff is supposed to be covered by the ABI. Consider that if
> it didn't then you wouldn't be able to use any of the standard libraries
> without recompiling them for each compiler since a number of standard library
> APIs depend on structs like timeval or stat.

Maybe.  My experience with these sorts of problems is fairly old (hard
lessons from libjpeg development in the mid-90s), but what I learned at
the time is that all the standard Unix library interfaces are carefully
designed to be fairly impervious to struct padding rules (eg, all the
fields are "int", or at least all the same size), and so you can get
apparent interoperability between compilers that don't agree on these
rules.  Meanwhile, Microsoft, who never met a feature they didn't like,
invented a foot-gun called #pragma pack, and then had to fix all their
headers to nail down the pack setting.  That in turn masks compatibility
issues on that platform, but only if you're willing to #pragma-ify all
of your own headers too.

In short, I don't trust anybody on this issue.  I have the scars to
remind me why not.
        regards, tom lane


Re: Building Windows Server Extensions Using VC++ 2005

From
Charlie Savage
Date:
Hi everyone,<br /><br /> Thanks for the feedback.  The reason for building extensions with MSVC on windows is to get
accessto the Micrsoft debugging tools since as far as I can see MingW/GDB cannot debug dynamically loaded dlls on the
Windowsplatform (or at least I haven't succeeded at doing it).<br /><br /> Anyway, with the few minor tweaks mentioned
thisseems to work fine.  I guess I would be surprised if it didn't since MinGW is commonly used for both creating and
usingDLLs on the Windows platform that integrate with programs and dlls built with VC++.  Other examples that work fine
arebuilding extensions for Python and Ruby using MingW, when both runtimes are built with VC++ (so the opposite case). 
Ofcourse, this compatibility might just be limited to the MinGW / VC++ combination, but that's all you need for this to
work.<br/><br /> Charlie<br /><br /> Tom Lane wrote: <blockquote cite="mid21532.1141490933@sss.pgh.pa.us"
type="cite"><prewrap="">"Magnus Hagander" <a class="moz-txt-link-rfc2396E"
href="mailto:mha@sollentuna.net"><mha@sollentuna.net></a>writes: </pre><blockquote type="cite"><pre wrap="">The
problemhere is that the backend is built with mingw but the
 
extension with msvc.   </pre></blockquote><pre wrap="">
I don't think that it's very reasonable to expect that to work.
The two compilers very likely have different rules for struct
packing, to take just the first gotcha.  Maybe they are compatible
enough that it will work, but if it does not we cannot fix it.
        regards, tom lane

 </pre></blockquote>

Re: Building Windows Server Extensions Using VC++ 2005

From
Bruce Momjian
Date:
Charlie Savage wrote:
> Hi everyone,
>
> Thanks for the feedback.  The reason for building extensions with MSVC
> on windows is to get access to the Micrsoft debugging tools since as far
> as I can see MingW/GDB cannot debug dynamically loaded dlls on the
> Windows platform (or at least I haven't succeeded at doing it).
>
> Anyway, with the few minor tweaks mentioned this seems to work fine.  I
> guess I would be surprised if it didn't since MinGW is commonly used for
> both creating and using DLLs on the Windows platform that integrate with
> programs and dlls built with VC++.  Other examples that work fine are
> building extensions for Python and Ruby using MingW, when both runtimes
> are built with VC++ (so the opposite case).  Of course, this
> compatibility might just be limited to the MinGW / VC++ combination, but
> that's all you need for this to work.

OK, I improved the STRINGS_H macro check and added DLLIMPORT in case
Win32 users don't export everything.  Added comments.  This is all 8.2
stuff.

--
  Bruce Momjian   http://candle.pha.pa.us
  SRA OSS, Inc.   http://www.sraoss.com

  + If your life is a hard drive, Christ can be your backup. +
Index: src/include/c.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/c.h,v
retrieving revision 1.197
diff -c -c -r1.197 c.h
*** src/include/c.h    3 Mar 2006 21:35:46 -0000    1.197
--- src/include/c.h    5 Mar 2006 04:39:27 -0000
***************
*** 57,62 ****
--- 57,64 ----
  #else
  #if defined(_MSC_VER) || defined(__BORLANDC__)
  #define WIN32_CLIENT_ONLY
+ /* Some use MinGW-generated pg_config.h but MSVC for extensions. */
+ #undef HAVE_STRINGS_H
  #endif
  #endif
  #include "postgres_ext.h"
***************
*** 66,73 ****
  #include <string.h>
  #include <stddef.h>
  #include <stdarg.h>
! /* Some use MinGW-generated pg_config.h but MSVC for extensions. */
! #if defined(HAVE_STRINGS_H) && !defined(WIN32_CLIENT_ONLY)
  #include <strings.h>
  #endif
  #include <sys/types.h>
--- 68,74 ----
  #include <string.h>
  #include <stddef.h>
  #include <stdarg.h>
! #ifdef HAVE_STRINGS_H
  #include <strings.h>
  #endif
  #include <sys/types.h>
Index: src/include/fmgr.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/fmgr.h,v
retrieving revision 1.40
diff -c -c -r1.40 fmgr.h
*** src/include/fmgr.h    15 Oct 2005 02:49:41 -0000    1.40
--- src/include/fmgr.h    5 Mar 2006 04:39:28 -0000
***************
*** 293,302 ****
  /* Expected signature of an info function */
  typedef Pg_finfo_record *(*PGFInfoFunction) (void);

! /* Macro to build an info function associated with the given function name */
!
  #define PG_FUNCTION_INFO_V1(funcname) \
! extern Pg_finfo_record * CppConcat(pg_finfo_,funcname) (void); \
  Pg_finfo_record * \
  CppConcat(pg_finfo_,funcname) (void) \
  { \
--- 293,305 ----
  /* Expected signature of an info function */
  typedef Pg_finfo_record *(*PGFInfoFunction) (void);

! /*
!  *    Macro to build an info function associated with the given function name.
!  *    Win32 loadable functions usually link with 'dlltool --export-all', but it
!  *    doesn't hurt to add DLLIMPORT in case they don't.
!  */
  #define PG_FUNCTION_INFO_V1(funcname) \
! extern DLLIMPORT Pg_finfo_record * CppConcat(pg_finfo_,funcname) (void); \
  Pg_finfo_record * \
  CppConcat(pg_finfo_,funcname) (void) \
  { \