<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii"><meta name=Generator content="Microsoft Word 12 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Verdana;
        panose-1:2 11 6 4 3 5 4 4 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p
        {mso-style-priority:99;
        mso-margin-top-alt:auto;
        margin-right:0in;
        mso-margin-bottom-alt:auto;
        margin-left:0in;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";}
span.EmailStyle18
        {mso-style-type:personal-reply;
        font-family:"Verdana","sans-serif";
        color:#1F497D;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=EN-US link=blue vlink=purple><div class=WordSection1><div><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in'><div><div><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:10.0pt;color:#1F497D'>&nbsp;</span><o:p></o:p></p><p><span style='font-size:10.0pt;color:#1F497D'>1.</span><span style='font-size:7.0pt;color:#1F497D'>&nbsp;&nbsp;&nbsp; </span><span style='font-size:10.0pt;color:#1F497D'>Modify the makefiles for your SDK so that it runs release-XXXX-dev\gdal\swig\python\setup.py with the &#8220;bdist --formats=wininst&#8221; option. This will produce an installation program such as gdal-1.7.3.win32-py2.5.exe. This is what the user will run to install the Python bindings together with a private copy of the GDAL DLLs used just by those bindings. On Python 2.6 and later, we probably want &#8220;bdist --formats=msi&#8221; to produce a .msi file rather than a .exe, because Windows likes .msi files much better than .exes for security purposes. IIRC, Python 2.5 and earlier do not have the msi option.</span><o:p></o:p></p><p><span style='font-size:10.0pt;color:#1F497D'>&nbsp;</span><o:p></o:p></p></div></div></blockquote><div><p class=MsoNormal>This can be done fairly easily. Does this mean we would require each build for multiple python versions?<span style='color:#1F497D'><o:p></o:p></span></p><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif";color:#1F497D'><o:p>&nbsp;</o:p></span></p><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif";color:#1F497D'>Yes, it would mean that. One build for Python 2.5, one for 2.6, one for 2.7, etc. This is how it is typically done.<o:p></o:p></span></p><p class=MsoNormal><span style='color:#1F497D'><o:p>&nbsp;</o:p></span></p><p class=MsoNormal>&nbsp;<o:p></o:p></p></div><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in'><div><div><p><span style='font-size:10.0pt;color:#1F497D'>2.</span><span style='font-size:7.0pt;color:#1F497D'>&nbsp;&nbsp;&nbsp; </span><span style='font-size:10.0pt;color:#1F497D'>Modify release-XXXX-dev\gdal\swig\python\setup.py to include the GDAL DLLs and data files in the data_files list that is passed to the setup() function. Make sure it is only done for Windows (Python code can check that). The goal is to have the installation program create the following kind of installation:</span><o:p></o:p></p><p><span style='font-size:10.0pt;color:#1F497D'>&nbsp;</span><o:p></o:p></p></div></div></blockquote><div><p class=MsoNormal>Hmmm. I'm keen to avoid any local modifications in the compiled files throughout the build system. Do we have some option to load this infromation from an external file (which is probably loaded by setup.py if exists)? Or I must write a custom setup2.py containing this customization.<br><br><span style='color:#1F497D'><o:p></o:p></span></p><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif";color:#1F497D'>I was not saying that setup.py be forked and a special copy exist for windows. I was saying that setup.py should internally check whether it was being executed on Windows (check Python&#8217;s sys.platform variable), and then perform special logic. But this may be moot because it sounded like Frank was not keen on my suggestion of enclosing a private copy of the GDAL DLLs with the Python bindings. If we avoid my suggestion then we are left with the idea of putting them in \Program Files\GDAL. In that case, we would not need to modify setup.py for this purpose. <o:p></o:p></span></p><p class=MsoNormal><br>&nbsp;<o:p></o:p></p></div><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in'><div><div><p><span style='font-size:10.0pt;color:#1F497D'>3.</span><span style='font-size:7.0pt;color:#1F497D'>&nbsp;&nbsp;&nbsp; </span><span style='font-size:10.0pt;color:#1F497D'>Introduce a new file release-XXXX-dev\gdal\swig\python\extensions\_gdal_dll_loader.cpp. This file will call GetDllDirectory to find the current DLL directory setting, call SetDllDirectory to C:\PythonXX\Lib\site-packages\osgeo\bin (or wherever the Python instance is installed), call LoadLibrary(&quot;gdal17.dll&quot;), and call SetDllDirectory back to what it was before. There are more details to consider. For example, we might want to have it call LoadLibrary first to see if it can load the GDAL DLL from the PATH, allowing the user to use their own GDAL DLLs without having to overwrite the ones in the Python directory. Or we might <u>not</u> want to do that, with the idea that the GDAL Python bindings must be tightly coupled to a particular version of GDAL&#8217;s DLLs.</span><o:p></o:p></p><p><span style='font-size:10.0pt;color:#1F497D'>&nbsp;</span><o:p></o:p></p></div></div></blockquote><div><p class=MsoNormal style='margin-bottom:12.0pt'>That seems to be quite complicated, not sure it that's working for those libraries using LoadLibrary binding at run time. Wouldn't that be better getting back to add the location to the PATH of the process in a loader.py (using SetEnvironmentVariable).<o:p></o:p></p><p class=MsoNormal style='margin-bottom:12.0pt'><span style='font-size:10.0pt;font-family:"Verdana","sans-serif";color:#1F497D'>I do not think it would be good to tamper with setting the PATH. I am not certain, but I think Python&#8217;s environment handler may call _putenv rather than SetEnvironmentVariable, or something like that, which can cause some problems. It might be better just to use SetDllDirectory. Also, as Chris pointed out, the Python ctypes module can be used to call win32 APIs. This would eliminate the need for a new _gdal_dll_loader module. Instead, the try/except block that I described below would just call win32 directly via ctypes. It could do the necessary SetDllDirectory/LoadLibrary/etc itself.<o:p></o:p></span></p><p class=MsoNormal style='margin-bottom:12.0pt'><span style='font-size:10.0pt;font-family:"Verdana","sans-serif";color:#1F497D'><o:p>&nbsp;</o:p></span></p></div><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in'><div><div><p class=MsoNormal><o:p>&nbsp;</o:p></p><p><span style='font-size:10.0pt;color:#1F497D'>5.</span><span style='font-size:7.0pt;color:#1F497D'>&nbsp;&nbsp;&nbsp; </span><span style='font-size:10.0pt;color:#1F497D'>Modify gdal.py, osr.py, and so on to do something like this:</span><o:p></o:p></p><p><span style='font-size:10.0pt;color:#1F497D'>&nbsp;</span><o:p></o:p></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:1.0in'><span style='font-size:10.0pt;color:#1F497D'>import sys</span><o:p></o:p></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:1.0in'><span style='font-size:10.0pt;color:#1F497D'>if sys.platform == 'win32':&nbsp;&nbsp;&nbsp;&nbsp; # TODO: add check for Windows x64 as well</span><o:p></o:p></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:1.0in'><span style='font-size:10.0pt;color:#1F497D'>&nbsp;&nbsp;&nbsp; try:</span><o:p></o:p></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:1.0in'><span style='font-size:10.0pt;color:#1F497D'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; import osgeo._gdal_dll_loader&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # As part of this, Python will call an &#8220;init&#8221; function inside. That function will do the SetDllDirectory, etc.</span><o:p></o:p></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:1.0in'><span style='font-size:10.0pt;color:#1F497D'>&nbsp;&nbsp;&nbsp; except:</span><o:p></o:p></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:1.0in'><span style='font-size:10.0pt;color:#1F497D'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pass</span><o:p></o:p></p></div></div></blockquote><div><p class=MsoNormal><br>Such changes can be done in the SWIG interface files easily.<span style='color:#1F497D'><o:p></o:p></span></p><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif";color:#1F497D'><o:p>&nbsp;</o:p></span></p><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif";color:#1F497D'>Sounds good to me.<o:p></o:p></span></p><p class=MsoNormal><br>&nbsp;<o:p></o:p></p></div><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in'><div><div><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:10.0pt;color:#1F497D'>&nbsp;</span><o:p></o:p></p><p><span style='font-size:10.0pt;color:#1F497D'>6.</span><span style='font-size:7.0pt;color:#1F497D'>&nbsp;&nbsp;&nbsp; </span><span style='font-size:10.0pt;color:#1F497D'>Do whatever is necessary to ensure the GDAL_DATA etc are properly set up inside GDAL. I can&#8217;t remember if this will &#8220;just work&#8221; using directories named gdal-data, gdal-plugins, or if it is necessary for the _gdal_dll_loader.pyd to call some GDAL functions to make it happen.</span><o:p></o:p></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:10.0pt;color:#1F497D'>&nbsp;</span><o:p></o:p></p></div></div></blockquote><div><p class=MsoNormal style='margin-bottom:12.0pt'><br>I guess this could also be set form a python script (probably from loader.py)<span style='color:#1F497D'><o:p></o:p></span></p><p class=MsoNormal style='margin-bottom:12.0pt'><span style='font-size:10.0pt;font-family:"Verdana","sans-serif";color:#1F497D'>If we follow the \Program Files\GDAL suggestion, then I further suggest that GDAL itself be modified to use that location as the default for GDAL_DATA, GDAL_PLUGINS, etc. That way the user does not have to set ANY environment variables for GDAL to work. That would be a major plus because, frankly, Windows users rarely have to set environment variables.<o:p></o:p></span></p><p class=MsoNormal style='margin-bottom:12.0pt'><br><br><o:p></o:p></p></div></div><p class=MsoNormal style='margin-bottom:12.0pt'>Best regards,<br><br>Tamas<o:p></o:p></p></div></body></html>