<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Sean Gillies (Posts about DLL)</title><link>https://sgillies.net/</link><description></description><atom:link href="https://sgillies.net/tags/dll.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Sun, 31 Dec 2023 01:26:22 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Fix for Shapely's GEOS library loading bug in 1.7a2</title><link>https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html</link><dc:creator>Sean Gillies</dc:creator><description>&lt;p&gt;Including GDAL and GEOS in binary wheels that go to the Python Package Index
(PyPI) has been good for users of fiona, rasterio, and shapely, but has also
exposed Python GIS programmers on OS X to a perplexing bug. Shapely's issue
&lt;a class="reference external" href="https://github.com/Toblerity/Shapely/issues/553"&gt;#553&lt;/a&gt; has been weighing on
me for a long time. It's been hard to understand, hard to explain, and bites
very hard. The short program below will trigger the bug on any version of OS
X with any version of fiona and any version of shapely before
1.7a2 which is installed using a wheel from PyPI.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code python"&gt;&lt;a id="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-1" name="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-1" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_b9b10ee35f2d4fefb89d8134d2c43334-1"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# crash.py&lt;/span&gt;
&lt;a id="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-2" name="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-2" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_b9b10ee35f2d4fefb89d8134d2c43334-2"&gt;&lt;/a&gt;
&lt;a id="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-3" name="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-3" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_b9b10ee35f2d4fefb89d8134d2c43334-3"&gt;&lt;/a&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;fiona&lt;/span&gt;
&lt;a id="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-4" name="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-4" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_b9b10ee35f2d4fefb89d8134d2c43334-4"&gt;&lt;/a&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;shapely.geometry&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;
&lt;a id="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-5" name="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-5" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_b9b10ee35f2d4fefb89d8134d2c43334-5"&gt;&lt;/a&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;shapely.ops&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;unary_union&lt;/span&gt;
&lt;a id="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-6" name="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-6" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_b9b10ee35f2d4fefb89d8134d2c43334-6"&gt;&lt;/a&gt;
&lt;a id="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-7" name="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-7" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_b9b10ee35f2d4fefb89d8134d2c43334-7"&gt;&lt;/a&gt;
&lt;a id="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-8" name="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-8" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_b9b10ee35f2d4fefb89d8134d2c43334-8"&gt;&lt;/a&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Buffering points to create polygons"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-9" name="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-9" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_b9b10ee35f2d4fefb89d8134d2c43334-9"&gt;&lt;/a&gt;&lt;span class="n"&gt;SHAPES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;a id="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-10" name="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-10" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_b9b10ee35f2d4fefb89d8134d2c43334-10"&gt;&lt;/a&gt;
&lt;a id="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-11" name="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-11" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_b9b10ee35f2d4fefb89d8134d2c43334-11"&gt;&lt;/a&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Computing union of polygons"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-12" name="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-12" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_b9b10ee35f2d4fefb89d8134d2c43334-12"&gt;&lt;/a&gt;&lt;span class="n"&gt;union&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;unary_union&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SHAPES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-13" name="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-13" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_b9b10ee35f2d4fefb89d8134d2c43334-13"&gt;&lt;/a&gt;
&lt;a id="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-14" name="rest_code_b9b10ee35f2d4fefb89d8134d2c43334-14" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_b9b10ee35f2d4fefb89d8134d2c43334-14"&gt;&lt;/a&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Union: &lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;union&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code console"&gt;&lt;a id="rest_code_1013a652070344fab205b1cad20eb23e-1" name="rest_code_1013a652070344fab205b1cad20eb23e-1" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_1013a652070344fab205b1cad20eb23e-1"&gt;&lt;/a&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;python crash.py
&lt;a id="rest_code_1013a652070344fab205b1cad20eb23e-2" name="rest_code_1013a652070344fab205b1cad20eb23e-2" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_1013a652070344fab205b1cad20eb23e-2"&gt;&lt;/a&gt;&lt;span class="go"&gt;Buffering points to create polygons&lt;/span&gt;
&lt;a id="rest_code_1013a652070344fab205b1cad20eb23e-3" name="rest_code_1013a652070344fab205b1cad20eb23e-3" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_1013a652070344fab205b1cad20eb23e-3"&gt;&lt;/a&gt;&lt;span class="go"&gt;Computing union of polygons&lt;/span&gt;
&lt;a id="rest_code_1013a652070344fab205b1cad20eb23e-4" name="rest_code_1013a652070344fab205b1cad20eb23e-4" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_1013a652070344fab205b1cad20eb23e-4"&gt;&lt;/a&gt;&lt;span class="go"&gt;Assertion failed: (!static_cast&amp;lt;bool&amp;gt;("should never be reached")), function itemsTree, file AbstractSTRtree.cpp, line 373.&lt;/span&gt;
&lt;a id="rest_code_1013a652070344fab205b1cad20eb23e-5" name="rest_code_1013a652070344fab205b1cad20eb23e-5" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_1013a652070344fab205b1cad20eb23e-5"&gt;&lt;/a&gt;&lt;span class="go"&gt;Abort trap: 6&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The unary_union function uses a GEOS STRtree and an assertion that should
never be reached is in fact reached and the program aborts.&lt;/p&gt;
&lt;p&gt;There has been a work-around – import shapely before importing other modules
that are dynamically linked with GEOS, such as fiona and rasterio – but that's
smelly and hard to ensure in a complex project.&lt;/p&gt;
&lt;p&gt;The problem exists in a small niche: one operating system and one kind of
program, one that that loads GEOS twice in different ways. Once when fiona's
extension modules are loaded and cause the linked GEOS library to be loaded as
with any compiled program, and once again when shapely is imported and it calls
&lt;code class="docutils literal"&gt;dlopen&lt;/code&gt; from python to load GEOS. I've found no diagnosis or solution of
a similar problem on the web. Was the problem in GEOS? Was it in the library
files that I built for the fiona, rasterio, and shapely wheels? Was the bug in
delocate, the program I use to find dependencies and bundle them into the
wheels? I asked GEOS developers and folks at work, to no avail. I was stumped
for a long time.&lt;/p&gt;
&lt;p&gt;I asked Even Rouault about the issue and he suggested a solution might be found
in being more careful about using the correct mode with &lt;code class="docutils literal"&gt;dlopen&lt;/code&gt; and he
offered some example Python code that included this: &lt;code class="docutils literal"&gt;handle = CDLL(None)&lt;/code&gt;.
My first thought was "can we use the ctypes CDLL class like this?" The docs say
that the first argument is a path to a library file and that's how I've been
using it in Shapely.&lt;/p&gt;
&lt;p&gt;While looking for guidance on passing &lt;code class="docutils literal"&gt;None&lt;/code&gt; to the CDLL constructor, I found
some commented code in &lt;a class="reference external" href="https://eli.thegreenplace.net/2013/03/09/python-ffi-with-ctypes-and-cffi"&gt;https://eli.thegreenplace.net/2013/03/09/python-ffi-with-ctypes-and-cffi&lt;/a&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code text"&gt;&lt;a id="rest_code_159c7825af8942fc9bacbc71fa3c6e8a-1" name="rest_code_159c7825af8942fc9bacbc71fa3c6e8a-1" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_159c7825af8942fc9bacbc71fa3c6e8a-1"&gt;&lt;/a&gt;# CDLL(None) invokes dlopen(NULL), which loads the currently running
&lt;a id="rest_code_159c7825af8942fc9bacbc71fa3c6e8a-2" name="rest_code_159c7825af8942fc9bacbc71fa3c6e8a-2" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_159c7825af8942fc9bacbc71fa3c6e8a-2"&gt;&lt;/a&gt;# process - in our case Python itself. Since Python is linked with
&lt;a id="rest_code_159c7825af8942fc9bacbc71fa3c6e8a-3" name="rest_code_159c7825af8942fc9bacbc71fa3c6e8a-3" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_159c7825af8942fc9bacbc71fa3c6e8a-3"&gt;&lt;/a&gt;# libc, readdir_r will be found there.
&lt;a id="rest_code_159c7825af8942fc9bacbc71fa3c6e8a-4" name="rest_code_159c7825af8942fc9bacbc71fa3c6e8a-4" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_159c7825af8942fc9bacbc71fa3c6e8a-4"&gt;&lt;/a&gt;# Alternatively, we can just explicitly load 'libc.so.6'.
&lt;a id="rest_code_159c7825af8942fc9bacbc71fa3c6e8a-5" name="rest_code_159c7825af8942fc9bacbc71fa3c6e8a-5" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_159c7825af8942fc9bacbc71fa3c6e8a-5"&gt;&lt;/a&gt;lib = CDLL(None)
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The OS X dlopen man page doesn't exactly say that,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;dlopen() examines the mach-o file specified by path.  If the file is
compatible with the current process and has not already been loaded into
the current process, it is loaded and linked.  After being linked, if it
contains any initializer functions, they are called, before dlopen()
returns.  dlopen() can load dynamic libraries and bundles.  It returns
a handle that can be used with dlsym() and dlclose().  A second call to
dlopen() with the same path will return the same handle, but the internal
reference count for the handle will be incremented.  Therefore all dlopen()
calls should be balanced with a dlclose() call.&lt;/p&gt;
&lt;p&gt;If a null pointer is passed in path, dlopen() returns a handle equivalent
to RTLD_DEFAULT.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;but the POSIX spec is clear that &lt;code class="docutils literal"&gt;dlopen(NULL)&lt;/code&gt; returns a handle to a global
symbols object and that's what I observe on my MacBook. Here's an interpreter
session where I import fiona and look in the global symbols object for a GDAL
C API function.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code pycon"&gt;&lt;a id="rest_code_d140df24a4c24f57908d8d1577f53613-1" name="rest_code_d140df24a4c24f57908d8d1577f53613-1" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_d140df24a4c24f57908d8d1577f53613-1"&gt;&lt;/a&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;fiona&lt;/span&gt;
&lt;a id="rest_code_d140df24a4c24f57908d8d1577f53613-2" name="rest_code_d140df24a4c24f57908d8d1577f53613-2" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_d140df24a4c24f57908d8d1577f53613-2"&gt;&lt;/a&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;ctypes&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CDLL&lt;/span&gt;
&lt;a id="rest_code_d140df24a4c24f57908d8d1577f53613-3" name="rest_code_d140df24a4c24f57908d8d1577f53613-3" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_d140df24a4c24f57908d8d1577f53613-3"&gt;&lt;/a&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CDLL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_d140df24a4c24f57908d8d1577f53613-4" name="rest_code_d140df24a4c24f57908d8d1577f53613-4" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_d140df24a4c24f57908d8d1577f53613-4"&gt;&lt;/a&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GDALGetDriverCount&lt;/span&gt;
&lt;a id="rest_code_d140df24a4c24f57908d8d1577f53613-5" name="rest_code_d140df24a4c24f57908d8d1577f53613-5" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_d140df24a4c24f57908d8d1577f53613-5"&gt;&lt;/a&gt;&lt;span class="go"&gt;&amp;lt;_FuncPtr object at 0x111a3eb38&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_d140df24a4c24f57908d8d1577f53613-6" name="rest_code_d140df24a4c24f57908d8d1577f53613-6" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_d140df24a4c24f57908d8d1577f53613-6"&gt;&lt;/a&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GDALGetDriverCount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a id="rest_code_d140df24a4c24f57908d8d1577f53613-7" name="rest_code_d140df24a4c24f57908d8d1577f53613-7" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_d140df24a4c24f57908d8d1577f53613-7"&gt;&lt;/a&gt;&lt;span class="go"&gt;187&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When fiona is imported, Python calls dlopen with the path to fiona's extension
(.so) modules, and as these are liked with libgdal, the GDAL library is loaded.
Now, libgdal is linked with libgeos_c, so will we find GEOS C API functions in
the global symbols object?&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code pycon"&gt;&lt;a id="rest_code_abbe7aaa20ca464e945b7931bc624d8b-1" name="rest_code_abbe7aaa20ca464e945b7931bc624d8b-1" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_abbe7aaa20ca464e945b7931bc624d8b-1"&gt;&lt;/a&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;initGEOS&lt;/span&gt;
&lt;a id="rest_code_abbe7aaa20ca464e945b7931bc624d8b-2" name="rest_code_abbe7aaa20ca464e945b7931bc624d8b-2" href="https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html#rest_code_abbe7aaa20ca464e945b7931bc624d8b-2"&gt;&lt;/a&gt;&lt;span class="go"&gt;&amp;lt;_FuncPtr object at 0x111a3fb38&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Yes. This changes everything. The problem that has bedeviled shapely users is
caused by using dlopen to load a library that's already been loaded. We can avoid
the problem by detecting whether libgeos_c has already been loaded and skipping
the troublesome dlopen call. I've done this for shapely and made a new 1.7
pre-release. Please considering running &lt;code class="docutils literal"&gt;pip install &lt;span class="pre"&gt;-U&lt;/span&gt; &lt;span class="pre"&gt;--pre&lt;/span&gt; shapely&lt;/code&gt; to try
it out.&lt;/p&gt;
&lt;p&gt;The OS X man page for dlsym says that looking up functions in the global handle
is the slowest possible approach, but ctypes does cache the addresses of
functions it finds and my test programs don't run measurably slower, so this
just might work out.&lt;/p&gt;
&lt;p&gt;I'd like to understand why this problem doesn't also occur on Linux. Is it
because of differences in the library loaders or the executable file formats
themselves? Is there subtle platform-specific bug in GEOS? I'll write more if
I get to the bottom of this.&lt;/p&gt;</description><category>ctypes</category><category>DLL</category><category>geos</category><category>python</category><category>shapely</category><category>work</category><guid>https://sgillies.net/2019/06/23/fix-for-geos-dll-bug-shapely-1-7a2.html</guid><pubDate>Sun, 23 Jun 2019 19:54:00 GMT</pubDate></item></channel></rss>