<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
Hi all,
<p>I have a question concerning C code defining a new function for postgis:
<p>I'm trying to test gpc in association with postgis.
<br>I wrote a C function taking 2 geometries in input, returning a geometry.
<br>It converts the input geometries (POLYGON3D) into gpc objects (works
fine: I can display the right coordinates)
<br>then run a gpc clipping operation (union) on the 2 geometries,
<br>And finally, converts the result into a POLYGON3D.
<p>When displaying the result's coordinates, all is ok, it appears to be
a valid POLYGON3D, all its fields are correct.
<p>Then, I call the make_oneobj_geometry function to convert the POLYGON3D
into a GEOMTRY, and call PG_RETURN_POINTER with the converted object.
<br>After the call, I tested the type, SRID, nobjs attributes of the GEOMETRY,
they are all correct.
<p>PostgreSQL crashes when I call my SQL function relying on the C function
with the following error message:
<p><tt>psql:/tmp/scot_gpc.sql:8: pqReadData() -- backend closed the channel
unexpectedly.</tt>
<br><tt>        This probably means
the backend terminated abnormally</tt>
<br><tt>        before or while processing
the request.</tt>
<br><tt>psql:/tmp/scot_gpc.sql:8: connection to server was lost</tt>
<p>When I call PG_RETURN_NULL instead, it works: a null result is returned
(:->).
<br>Am I doing something wrong with make_oneobj_geometry, or is it PG_RETURN_POINTER 
?
<p>My config: Postgres 7.1.3 running on windows2000, cygwin.
<br>Postgis 0.6.2.
<br>gpc 2.31 sources.
<br>To compile and link my source code, I have modified the postgis makefile
to include my own files, as I was unable to produce a valid dll (I'm on
Windows), so my function is in postgis.dll.
<p>Thanx for any advice.
<p>Nicolas Ribot.
<p>Following the source code of my function,
<p><tt>PG_FUNCTION_INFO_V1(test_geogpc);</tt>
<br><tt>Datum test_geogpc(PG_FUNCTION_ARGS) {</tt>
<br><tt> GEOMETRY      *geom1 =  (GEOMETRY
*)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));</tt>
<br><tt> GEOMETRY      *geom2 =  (GEOMETRY
*)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));</tt>
<br><tt> GEOMETRY      *result = (GEOMETRY
*) palloc(sizeof(GEOMETRY) );</tt>
<br><tt> POLYGON3D          
*poly1;</tt>
<br><tt> POLYGON3D          
*poly2;</tt>
<br><tt> POLYGON3D          
*poly_res;</tt>
<br><tt> int32        *offset1;</tt>
<br><tt> int32              
*offset2;</tt>
<br><tt> int     poly_res_size;</tt>
<br><tt> char               
*o1;</tt>
<br><tt> char               
*o2;</tt>
<br><tt> /* gpc types */</tt>
<br><tt> gpc_polygon gpcsubject, gpcclip, gpcresult;</tt>
<p><tt>elog(NOTICE,"Entering test_geogpc. Int: %d", toto);</tt>
<br><tt> // looks at the input geometries type</tt>
<br><tt> if (geom1->type != POLYGONTYPE || geom2->type != POLYGONTYPE)
{</tt>
<br><tt>  elog(ERROR,"Incompatible types for 2 geometries (expected
POLYGON)");</tt>
<br><tt>  PG_RETURN_NULL();</tt>
<br><tt> }</tt>
<p><tt> if (geom1->SRID != geom2->SRID) {</tt>
<br><tt>  elog(ERROR,"Operation on two GEOMETRIES with different SRIDs");</tt>
<br><tt>  PG_RETURN_NULL();</tt>
<br><tt> }</tt>
<br><tt> // creates the 2 polygons and 2 gpc polygons on which operations
will be done</tt>
<br><tt> offset1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+
sizeof(int32) * geom1->nobjs );</tt>
<br><tt> offset2 = (int32 *) ( ((char *) &(geom2->objType[0] ))+
sizeof(int32) * geom2->nobjs );</tt>
<p><tt> o1 = (char *) geom1 +offset1[0];</tt>
<br><tt> o2 = (char *) geom2 +offset2[0];</tt>
<p><tt> poly1 = (POLYGON3D *)o1;</tt>
<br><tt> poly2 = (POLYGON3D *)o2;</tt>
<p><tt> // creates gpc polygon from postgis polygons:</tt>
<br><tt> scot_gpc_read_polygon(poly1, &gpcsubject);</tt>
<br><tt> scot_gpc_read_polygon(poly2, &gpcclip);</tt>
<p><tt> // perform the clipping operation (union geom1-geom2 for test)</tt>
<br><tt> gpc_polygon_clip(GPC_UNION, &gpcsubject, &gpcclip,
&gpcresult);</tt>
<p><tt> //Convert result to opengis polygon:</tt>
<br><tt> poly_res = scot_gpc_write_polygon(&gpcresult, &poly_res_size);</tt>
<p><tt> result = make_oneobj_geometry(poly_res_size,</tt>
<br><tt>                              
(char *)poly_res,</tt>
<br><tt>                              
POLYGONTYPE,</tt>
<br><tt>                              
FALSE,</tt>
<br><tt>                              
geom1->SRID,</tt>
<br><tt>                              
geom1->scale,</tt>
<br><tt>                              
geom1->offsetX,</tt>
<br><tt>                              
geom1->offsetY</tt>
<br><tt>                              
);</tt>
<br><tt> // free memory for gpc polygons.</tt>
<br><tt> gpc_free_polygon(&gpcsubject);</tt>
<br><tt> gpc_free_polygon(&gpcclip);</tt>
<br><tt> gpc_free_polygon(&gpcresult);</tt>
<p><tt> PG_RETURN_POINTER(result);</tt>
<br><tt>}</tt>
<p>The SQL function definition
<p><tt>CREATE FUNCTION test_geogpc(GEOMETRY,GEOMETRY)</tt>
<br><tt>RETURNS GEOMETRY</tt>
<br><tt>AS 'C:/cygwin/usr/src/postgresql-7.1.3-2/contrib/postgis-0.6.2/postgis.dll'</tt>
<br><tt>LANGUAGE 'c'  with (isstrict);</tt>
<p><tt>and I call:</tt>
<br><tt>  select test_geogpc</tt>
<br><tt>  (</tt>
<br><tt>  (select geom from testgpc where id=1),</tt>
<br><tt>  (select geom from testgpc where id=2)</tt>
<br><tt>  )</tt></html>