Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

"General Polygon Clipper library" wrapper with the help of Ffidl

269 views
Skip to first unread message

Thomas

unread,
Nov 12, 2012, 10:07:36 AM11/12/12
to
I'm currently working on a program, that requires polygon clipping.
i've found a lib that seems to do it's job quiet well.
It can be found here:

http://www.cs.man.ac.uk/~toby/alan/software/

I compiled the dll under windows with the help of MingW.
I asked myself how to load that dll and use the functions.
The wiki suggested ffidl. However it's doesn't seem to be that easy to use.

Functions and typedefs that need to be defined can be found in the gpc.h.
http://pastebin.com/JQTWLULh

I first tried to define the custom typedefs...

::ffidl::typedef gpc_vertex double double
::ffidl::typedef gpc_vertex_list int gpc_vertex
::ffidl::typedef gpc_polygon int int gpc_vertex_list
::ffidl::typedef gpc_tristrip int gpc_vertex_list

... but how to define enums?

And how to bind the functions?
Could anyone give an example?

Thanks in advance!

Regards




Uwe Klein

unread,
Nov 12, 2012, 11:32:07 AM11/12/12
to
Thomas wrote:
> I'm currently working on a program, that requires polygon clipping.
> i've found a lib that seems to do it's job quiet well.
> It can be found here:
>
> http://www.cs.man.ac.uk/~toby/alan/software/
>
> I compiled the dll under windows with the help of MingW.
> I asked myself how to load that dll and use the functions.
> The wiki suggested ffidl. However it's doesn't seem to be that easy to use.

use SWIG ?
http://www.swig.org/

uwe

Thomas

unread,
Nov 12, 2012, 4:06:18 PM11/12/12
to
wow swig looks amazing. i just tried to build it under mingw with swig.

here are commands and outputs (i used the tutorial as a reference http://www.swig.org/tutorial.html)
/include/tcl contains the tcl headers

% swig -tcl gpc.i
% gcc -fpic -c gpc.c gpc_wrap.c -I/include/tcl
gpc.c:1:0: Warnung: -fpic für Ziel ignoriert (der gesamte Code ist positionsunabhängig) [standardmäßig aktiviert]
gpc_wrap.c:1:0: Warnung: -fpic für Ziel ignoriert (der gesamte Code ist positionsunabhängig) [standardmäßig aktiviert]


% gcc -shared gpc.o gpc_wrap.o -o gpc.dll
gpc_wrap.o:gpc_wrap.c:(.text+0x96b): undefined reference to `_imp__Tcl_ResetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x97f): undefined reference to `_imp__Tcl_SetObjResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x9a3): undefined reference to `_imp__Tcl_SetErrorCode'
gpc_wrap.o:gpc_wrap.c:(.text+0x9b8): undefined reference to `_imp__Tcl_ResetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x9dc): undefined reference to `_imp__Tcl_SetErrorCode'
gpc_wrap.o:gpc_wrap.c:(.text+0xa07): undefined reference to `_imp__Tcl_AppendResult'
gpc_wrap.o:gpc_wrap.c:(.text+0xa24): undefined reference to `_imp__Tcl_NewStringObj'
gpc_wrap.o:gpc_wrap.c:(.text+0xa4c): undefined reference to `_imp__Tcl_ObjSetVar2'
gpc_wrap.o:gpc_wrap.c:(.text+0xad8): undefined reference to `_imp__Tcl_InitHashTable'
gpc_wrap.o:gpc_wrap.c:(.text+0xb82): undefined reference to `_imp__Tcl_DeleteHashEntry'
gpc_wrap.o:gpc_wrap.c:(.text+0xc00): undefined reference to `_imp__Tcl_VarEval'
gpc_wrap.o:gpc_wrap.c:(.text+0xc11): undefined reference to `_imp__Tcl_GetObjResult'
gpc_wrap.o:gpc_wrap.c:(.text+0xc29): undefined reference to `_imp__Tcl_GetStringFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0xc3c): undefined reference to `_imp__Tcl_ResetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0xc53): undefined reference to `_imp__Tcl_ResetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0xc81): undefined reference to `_imp__Tcl_VarEval'
gpc_wrap.o:gpc_wrap.c:(.text+0xc92): undefined reference to `_imp__Tcl_ResetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0xca9): undefined reference to `_imp__Tcl_GetObjResult'
gpc_wrap.o:gpc_wrap.c:(.text+0xcbb): undefined reference to `_imp__Tcl_GetStringFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0xda7): undefined reference to `_imp__Tcl_GetStringFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0xe37): undefined reference to `_imp__Tcl_GetStringFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0xf3b): undefined reference to `_imp__Tcl_NewStringObj'
gpc_wrap.o:gpc_wrap.c:(.text+0xfcc): undefined reference to `_imp__Tcl_NewStringObj'
gpc_wrap.o:gpc_wrap.c:(.text+0xfff): undefined reference to `_imp__Tcl_GetVar'
gpc_wrap.o:gpc_wrap.c:(.text+0x107d): undefined reference to `_imp__Tcl_SetVar'
gpc_wrap.o:gpc_wrap.c:(.text+0x10ed): undefined reference to `_imp__TclFreeObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1140): undefined reference to `_imp__Tcl_SetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x1164): undefined reference to `_imp__Tcl_GetStringFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1211): undefined reference to `_imp__Tcl_DeleteCommandFromToken'
gpc_wrap.o:gpc_wrap.c:(.text+0x13ff): undefined reference to `_imp__TclFreeObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1445): undefined reference to `_imp__Tcl_SetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x1469): undefined reference to `_imp__Tcl_GetStringFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1511): undefined reference to `_imp__TclFreeObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1556): undefined reference to `_imp__Tcl_DuplicateObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1567): undefined reference to `_imp__Tcl_SetObjResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x15bb): undefined reference to `_imp__Tcl_SetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x15da): undefined reference to `_imp__Tcl_SetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x1622): undefined reference to `_imp__Tcl_SetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x165b): undefined reference to `_imp__Tcl_GetStringFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1731): undefined reference to `_imp__TclFreeObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x17bb): undefined reference to `_imp__Tcl_SetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x17f9): undefined reference to `_imp__Tcl_SetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x1820): undefined reference to `_imp__Tcl_SetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x1850): undefined reference to `_imp__Tcl_GetStringResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x18e3): undefined reference to `_imp__Tcl_AppendElement'
gpc_wrap.o:gpc_wrap.c:(.text+0x197e): undefined reference to `_imp__Tcl_GetStringFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x199c): undefined reference to `_imp__Tcl_GetCommandInfo'
gpc_wrap.o:gpc_wrap.c:(.text+0x19c6): undefined reference to `_imp__Tcl_DuplicateObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1a08): undefined reference to `_imp__Tcl_GetStringFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1a30): undefined reference to `_imp__Tcl_CreateObjCommand'
gpc_wrap.o:gpc_wrap.c:(.text+0x1ab4): undefined reference to `_imp__Tcl_SetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x1aeb): undefined reference to `_imp__Tcl_GetStringFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1b73): undefined reference to `_imp__Tcl_GetStringFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1c02): undefined reference to `_imp__Tcl_GetObjResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x1c0c): undefined reference to `_imp__Tcl_DuplicateObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1c2e): undefined reference to `_imp__Tcl_GetStringFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1c66): undefined reference to `_imp__Tcl_DuplicateObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1c84): undefined reference to `_imp__Tcl_GetStringFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1ca6): undefined reference to `_imp__Tcl_SetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x1ccd): undefined reference to `_imp__Tcl_SetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x1d2b): undefined reference to `_imp__TclFreeObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1db0): undefined reference to `_imp__Tcl_CreateObjCommand'
gpc_wrap.o:gpc_wrap.c:(.text+0x1e2f): undefined reference to `_imp__Tcl_SetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x1e8e): undefined reference to `_imp__Tcl_GetStringFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1f03): undefined reference to `_imp__Tcl_GetLongFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x1fa5): undefined reference to `_imp__Tcl_GetDoubleFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x2027): undefined reference to `_imp__Tcl_GetStringFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x2049): undefined reference to `_imp__Tcl_GetStringFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x2068): undefined reference to `_imp__Tcl_GetStringFromObj'
gpc_wrap.o:gpc_wrap.c:(.text+0x2127): undefined reference to `_imp__Tcl_SetResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x21bc): undefined reference to `_imp__Tcl_AppendResult'
gpc_wrap.o:gpc_wrap.c:(.text+0x251c): undefined reference to `_imp__Tcl_InitHashTable'
gpc_wrap.o:gpc_wrap.c:(.text+0x2676): undefined reference to `_imp__Tcl_InitHashTable'
gpc_wrap.o:gpc_wrap.c:(.text+0x270f): undefined reference to `_imp__Tcl_PkgProvide'
gpc_wrap.o:gpc_wrap.c:(.text+0x2724): undefined reference to `_imp__Tcl_Eval'
gpc_wrap.o:gpc_wrap.c:(.text+0x2797): undefined reference to `_imp__Tcl_CreateObjCommand'
gpc_wrap.o:gpc_wrap.c:(.text+0x27eb): undefined reference to `_imp__Tcl_SetVar'
gpc_wrap.o:gpc_wrap.c:(.text+0x2833): undefined reference to `_imp__Tcl_TraceVar'
gpc_wrap.o:gpc_wrap.c:(.text+0x287b): undefined reference to `_imp__Tcl_TraceVar'
collect2.exe: Fehler: ld gab 1 als Ende-Status zurück

as you can see the dll is not compiled.
my gpc.i contains the following data:

%module gpc
%{
#include "gpc.h"
%}
#include "gpc.h"

any ideas whats wrong?

Christian Gollwitzer

unread,
Nov 12, 2012, 4:40:26 PM11/12/12
to
Am 12.11.12 22:06, schrieb Thomas:
> wow swig looks amazing. i just tried to build it under mingw with swig.
>
> here are commands and outputs (i used the tutorial as a reference http://www.swig.org/tutorial.html)
> /include/tcl contains the tcl headers
>
> % swig -tcl gpc.i
> % gcc -fpic -c gpc.c gpc_wrap.c -I/include/tcl
> gpc.c:1:0: Warnung: -fpic f�r Ziel ignoriert (der gesamte Code ist positionsunabh�ngig) [standardm��ig aktiviert]
> gpc_wrap.c:1:0: Warnung: -fpic f�r Ziel ignoriert (der gesamte Code ist positionsunabh�ngig) [standardm��ig aktiviert]
>
>
> % gcc -shared gpc.o gpc_wrap.o -o gpc.dll
> gpc_wrap.o:gpc_wrap.c:(.text+0x96b): undefined reference to `_imp__Tcl_ResetResult'

You fail to link against the Tcl library. Furthermore, you should make
use of stubs. Try:

gcc -fpic -DUSE_TCL_STUBS -c gpc.c gpc_wrap.c -I/include/tcl
gcc -shared gpc.o gpc_wrap.o -o gpc.dll /lib/tcl/tclstub85.lib
# adopt the path to the lib file to get it to link

Christian


Thomas

unread,
Nov 12, 2012, 4:51:51 PM11/12/12
to
> You fail to link against the Tcl library. Furthermore, you should make
>
> use of stubs. Try:
>
>
>
> gcc -fpic -DUSE_TCL_STUBS -c gpc.c gpc_wrap.c -I/include/tcl
>
> gcc -shared gpc.o gpc_wrap.o -o gpc.dll /lib/tcl/tclstub85.lib
>
> # adopt the path to the lib file to get it to link
>
>
>
> Christian

there are still errors :/

gpc_wrap.o:gpc_wrap.c:(.text+0x965): undefined reference to `tclStubsPtr'
gpc_wrap.o:gpc_wrap.c:(.text+0x978): undefined reference to `tclStubsPtr'
gpc_wrap.o:gpc_wrap.c:(.text+0x992): undefined reference to `tclStubsPtr'
gpc_wrap.o:gpc_wrap.c:(.text+0x9c4): undefined reference to `tclStubsPtr'
gpc_wrap.o:gpc_wrap.c:(.text+0x9d7): undefined reference to `tclStubsPtr'
gpc_wrap.o:gpc_wrap.c:(.text+0xa01): more undefined references to `tclStubsPtr' follow
gpc_wrap.o:gpc_wrap.c:(.text+0x28d5): undefined reference to `Tcl_InitStubs'
gpc_wrap.o:gpc_wrap.c:(.text+0x28e8): undefined reference to `tclStubsPtr'
gpc_wrap.o:gpc_wrap.c:(.text+0x290b): undefined reference to `tclStubsPtr'
gpc_wrap.o:gpc_wrap.c:(.text+0x293f): undefined reference to `tclStubsPtr'
gpc_wrap.o:gpc_wrap.c:(.text+0x29c5): undefined reference to `tclStubsPtr'
gpc_wrap.o:gpc_wrap.c:(.text+0x29fa): undefined reference to `tclStubsPtr'
gpc_wrap.o:gpc_wrap.c:(.text+0x2a4b): more undefined references to `tclStubsPtr' follow

Christian Gollwitzer

unread,
Nov 12, 2012, 5:28:00 PM11/12/12
to
Am 12.11.12 22:51, schrieb Thomas:
>> You fail to link against the Tcl library. Furthermore, you should make
>>
>> use of stubs. Try:
>>
>> gcc -fpic -DUSE_TCL_STUBS -c gpc.c gpc_wrap.c -I/include/tcl
>>
>> gcc -shared gpc.o gpc_wrap.o -o gpc.dll /lib/tcl/tclstub85.lib
>>
>> # adopt the path to the lib file to get it to link
>>
>>
>>
>> Christian
>
> there are still errors :/
>
> gpc_wrap.o:gpc_wrap.c:(.text+0x965): undefined reference to `tclStubsPtr'


This is more-or-less the same error, only for the stubs-version: gcc
fails to link against the Tcl-Library. Is the tclstub85.lib at the right
place? Have you compiled that one yourself, too, or is it from the
ActiveTcl distribution? What does "nm" tell about the library file?

I don't know about the current status of gcc linking against static
libraries for Visual C (I asumed it is simply working), and I don't have
this setup here now to test it for you, sorry.

Christian

elfi...@gmail.com

unread,
Nov 13, 2012, 1:26:59 AM11/13/12
to
nm showed nothing :/
i compiled tcl in mingw and used the created libstub.
at least gcc could now ling the object files and a dll was created.
i tried to load the dll in activestate's wish, but that didnt work.

the dll loads fine in mingw's compiled tclsh version.
after loading the dll i tried to check the new commands with
info commands * and info commands ::gpc*.
Sadly no new commands were added :(.

Christian Gollwitzer

unread,
Nov 13, 2012, 3:39:02 AM11/13/12
to
Am 13.11.12 07:26, schrieb elfi...@gmail.com:
> nm showed nothing :/
> i compiled tcl in mingw and used the created libstub.
> at least gcc could now ling the object files and a dll was created.
> i tried to load the dll in activestate's wish, but that didnt work.
>
> the dll loads fine in mingw's compiled tclsh version.

Congratulations! You managed the first step;) The dll not loading into
ActiveTcl is probably due to the dependence on gcc's libc. You could try
linking with -static to overcome this, but first you should try getting
it working with mingw's tclsh.

> after loading the dll i tried to check the new commands with
> info commands * and info commands ::gpc*.
> Sadly no new commands were added :(.


Strange. Did SWIG give any output? It also has a -Wall flag. Maybe this
gpc.h only includes other include files? By default, SWIG does not
recursively follow include files in order to avoid wrapping math.h,
stdio.h & friends.

You can also check SWIG's output. Wrapped functions compile to something
like

SWIGINTERN int
_wrap_HDFpp_getname(ClientData clientData SWIGUNUSED, Tcl_Interp
*interp, int objc, Tcl_Obj *CONST objv[]) {

(from one of my projects, HDFpp::getname was the original method)


Try adding a simple helloworld function to the gpc.h file like this

inline int helloworld(int i) { return 2*i; }

and see if it appears.

Christian

Thomas

unread,
Nov 13, 2012, 4:00:30 AM11/13/12
to
> Strange. Did SWIG give any output? It also has a -Wall flag. Maybe this
>
> gpc.h only includes other include files? By default, SWIG does not
>
> recursively follow include files in order to avoid wrapping math.h,
>
> stdio.h & friends.
>
>
>
> You can also check SWIG's output. Wrapped functions compile to something
>
> like
>
>
>
> SWIGINTERN int
>
> _wrap_HDFpp_getname(ClientData clientData SWIGUNUSED, Tcl_Interp
>
> *interp, int objc, Tcl_Obj *CONST objv[]) {
>
>
>
> (from one of my projects, HDFpp::getname was the original method)
>
>
>
>
>
> Try adding a simple helloworld function to the gpc.h file like this
>
>
>
> inline int helloworld(int i) { return 2*i; }
>
>
>
> and see if it appears.
>
>
>
> Christian

Hello,

i tried the same procedure on another computer with a different activestate tcl version.

i used activestate's tcl headers and the tclstub85.lib, which came with it.
my swig inpute file had an error, which i fixed.

and guess what? it linked and compiled just fine!

the dll is now loadable in activestate's wish.

% join [info commands gpc_*] \n
gpc_vertex_list_vertex_get
gpc_vertex_list_num_vertices_get
gpc_tristrip_num_strips_set
gpc_tristrip_strip_get
gpc_tristrip
gpc_vertex_x_get
gpc_write_polygon
gpc_tristrip_num_strips_get
gpc_add_contour
gpc_polygon_to_tristrip
gpc_polygon_num_contours_set
gpc_polygon_contour_set
gpc_polygon
gpc_free_polygon
gpc_free_tristrip
gpc_polygon_clip
gpc_vertex_y_set
gpc_polygon_num_contours_get
gpc_polygon_contour_get
gpc_vertex_list
gpc_tristrip_clip
gpc_polygon_hole_set
gpc_vertex_y_get
gpc_vertex
gpc_vertex_list_vertex_set
gpc_vertex_list_num_vertices_set
gpc_read_polygon
gpc_tristrip_strip_set
gpc_polygon_hole_get
gpc_vertex_x_set

as you can see the commands are all there now!
thanks so far.

i now need to figure out how to use that monster lol.

typedef struct /* Vertex list structure */
{
int num_vertices; /* Number of vertices in list */
gpc_vertex *vertex; /* Vertex array pointer */
} gpc_vertex_list;

thats the first problem i ran into.
how are those defined 'Vertex array pointer' in tcl?
adding a gpc_vertex and defining values for x and y are no problem.

my example.....

load gpc.dll

set vertex1 [gpc_vertex]
set vertex2 [gpc_vertex]
set vertex3 [gpc_vertex]

$vertex1 configure -x 0 -y 0
$vertex2 configure -x 1 -y 0
$vertex2 configure -x 0 -y 1

set vertex_list1 [gpc_vertex_list]

$vertex_list1 configure -num_vertices 3 -vertex [list $vertex1 $vertex2 $vertex3]

it returns:

TypeError in method 'gpc_vertex_list_vertex_set', argument 2 of type 'gpc_vertex *'




Christian Gollwitzer

unread,
Nov 13, 2012, 7:07:01 AM11/13/12
to
Am 13.11.12 10:00, schrieb Thomas:
> i tried the same procedure on another computer with a different activestate tcl version.
>
> i used activestate's tcl headers and the tclstub85.lib, which came with it.
> my swig inpute file had an error, which i fixed.
>
> and guess what? it linked and compiled just fine!
>
> the dll is now loadable in activestate's wish.


> % join [info commands gpc_*] \n
> gpc_vertex_list_vertex_get
> gpc_vertex_list_num_vertices_get

Congratulations so far:)

> i now need to figure out how to use that monster lol.
>
> typedef struct /* Vertex list structure */
> {
> int num_vertices; /* Number of vertices in list */
> gpc_vertex *vertex; /* Vertex array pointer */
> } gpc_vertex_list;
>
> thats the first problem i ran into.
> how are those defined 'Vertex array pointer' in tcl?
> adding a gpc_vertex and defining values for x and y are no problem.

Well, you ran into a point where it will be easier to extend it from the
C level. The problem with that code is, that it expects a contiguous
array of gpc_vertex, which you probably can't build from Tcl using SWIG
alone. SWIG does not understand that this is an array, it instead knows
only about raw pointers. The low-level variant would be a method to
allocate this thing from C; something like

gpc_vertex_list makelist(int n) {
gpc_vertex_list result;
result.num_vertices=n;
result.vertex = malloc(sizeof(gpc_vertex)*n);
return result;
}

and a corresponding free method+accessor for the nth element. Most
libraries I have seen so far profited from wrapping them up in a
(trivial) C++ class, which then was converted to Tcl by SWIG into a
usable form.

Christian

Uwe Klein

unread,
Nov 13, 2012, 7:42:53 AM11/13/12
to
Thomas wrote:
> i now need to figure out how to use that monster lol.

would looking at how OpenGL is SWIG wrapped help ?

uwe

elfi...@gmail.com

unread,
Nov 13, 2012, 8:28:08 AM11/13/12
to
> Well, you ran into a point where it will be easier to extend it from the
>
> C level. The problem with that code is, that it expects a contiguous
>
> array of gpc_vertex, which you probably can't build from Tcl using SWIG
>
> alone. SWIG does not understand that this is an array, it instead knows
>
> only about raw pointers. The low-level variant would be a method to
>
> allocate this thing from C; something like
>
>
>
> gpc_vertex_list makelist(int n) {
>
> gpc_vertex_list result;
>
> result.num_vertices=n;
>
> result.vertex = malloc(sizeof(gpc_vertex)*n);
>
> return result;
>
> }
>
>
>
> and a corresponding free method+accessor for the nth element. Most
>
> libraries I have seen so far profited from wrapping them up in a
>
> (trivial) C++ class, which then was converted to Tcl by SWIG into a
>
> usable form.
>
>
>
> Christian

hmm i might be at the end of my knowledge, heh.
i'm not that good in c to fully understand the lib and add the functions needed :(. i'll try to add helper functions tho.

thanks so far :)

Thomas

unread,
Nov 13, 2012, 9:12:46 AM11/13/12
to
> gpc_vertex_list makelist(int n) {
> gpc_vertex_list result;
> result.num_vertices=n;
> result.vertex = malloc(sizeof(gpc_vertex)*n);
> return result;
> }

that didn't work btw.

Christian Gollwitzer

unread,
Nov 13, 2012, 2:25:26 PM11/13/12
to
Am 13.11.12 15:12, schrieb Thomas:
When you say "didn't work"; what have you tried? First, I haven't
actually tried to compile this, there might be errors. Second, it was
meant to be used like this:

set new_vert [makelist 5]

to construct the vertex list. There is a need to add another accessor
function to be actually able to use it; it could look like this:

void set_vertex(gpc_vertex_list *list, int n, double x, double y) {
if (n<0 || n>= list->num_vertices) {
// throw error. This is painful if not using C++
// so I simply ignore it here
} else {
list->vertex[n].x=x;
list->vertex[n].y=y;
}
}

and an anologous get_vertex to read from that

// here we use the fact that SWIG returns a list of two values
// from the return value and from output
double get_vertex(gpc_vertex_list *list, int n, double *OUTPUT) {
double x=list->vertex[n].x;
OUTPUT=list->vertex[n].y;
return x;
}


If done correctly, you should be able to make your list from Tcl using

set new_vert [makelist 5]
set_vertex $new_vert 0 1.0 2.0
get_vertex $new_vert 0

etc...

Beware that I have NOT tried to compile this code.

I will not really try nor go on about it. You have to be able to use the
lib from C before you can do this, of course. Fortunately (I had a quick
look at the header file), from that point on it should almost work: It
seems you can use gpc_add_contour to build up your gpc_polygon from
vertex lists (though you need a way to make an uninitialized
gpc_polygon, where n=0). You'll also need to tell SWIG which of the
parameters are actually output parameters. YOu do this by typemaps. For
example, for gpc_polygon_clip to work, you must write

#ifdef SWIG
%apply gpc_polygon *OUTPUT { gpc_polygon * result_polygon };
#endif

*before* SWIG reads the definition for gpc_polygon_clip.

Yes, I know this is not as easy as you might have hoped. That's because
C isn't really object oriented and building the data structures in
memory is also a low-level thing in C. If it would be an equivalent C++
class, it would be easier, because than there is the semantics of
constructors, destructors, and accessors that allow SWIG to do
meaningful wrapping. In pure C, SWIG can't know whether a pointer
parameter is meant to hold an array, return a value, or an input
parameter. You can make using the lib from Tcl less painful by moving
the pain into these wrapper functions.

Christian


Thomas

unread,
Nov 14, 2012, 5:57:55 AM11/14/12
to
Hi,

i played around with the examples you gave me.
as a result, i ended up with the following functions in C.

gpc_vertex_list gpc_vertex_list_make(int n) {
gpc_vertex_list result;
result.num_vertices=n;
result.vertex = malloc(sizeof(gpc_vertex)*n);
return result;
}

gpc_polygon gpc_polygon_empty_make() {
gpc_polygon result;
gpc_vertex_list *list;
result.num_contours = 0;
result.hole = 0;
result.contour = list;
return result;
}

gpc_polygon gpc_polygon_create(gpc_vertex_list *list) {
gpc_polygon result;
result.num_contours = 1;
result.hole = 0;
result.contour = list;
return result;
}

int gpc_polygon_num_get(gpc_polygon *polygon) {
return polygon->num_contours;
}

gpc_vertex_list gpc_polygon_vertex_list_get(gpc_polygon *polygon, int n) {
gpc_vertex_list *result;
result = polygon->contour;
return result[n];
}

void gpc_vertex_set(gpc_vertex_list *list, int n, double x, double y) {
if (n < 0 || n >= list->num_vertices) {
// throw error. This is painful if not using C++
// so I simply ignore it here
} else {
list->vertex[n].x = x;
list->vertex[n].y = y;
}
}

double gpc_vertex_get(gpc_vertex_list *list, int n, double *result) {
if (n < 0 || n >= list->num_vertices) {
// throw error. This is painful if not using C++
// so I simply ignore it here
} else {
double x=list->vertex[n].x;
*result=list->vertex[n].y;
return x;
}
}

int gpc_vertex_num_get(gpc_vertex_list *list) {
return list->num_vertices;
}


my example in tcl looks like this:

console show

load gpc.dll

set vertex_list [gpc_vertex_list_make 4]
gpc_vertex_set $vertex_list 0 0 0
gpc_vertex_set $vertex_list 1 1 0
gpc_vertex_set $vertex_list 2 1 1
gpc_vertex_set $vertex_list 3 0 1

set vertex_list2 [gpc_vertex_list_make 4]
gpc_vertex_set $vertex_list2 0 3 3
gpc_vertex_set $vertex_list2 1 4 3
gpc_vertex_set $vertex_list2 2 4 4
gpc_vertex_set $vertex_list2 3 3 4

set polygon1 [gpc_polygon_create $vertex_list]

gpc_add_contour $polygon1 $vertex_list2 0

the last command doesn't work somehow. it crashes my wish instance.
i guess my gpc_polygon_create function is wrong?
it's kinda weird, because the lib function gpc_write_polygon (creates a text file with all the points in it) works just fine with the polygon created with gpc_polygon_create!

my question is. are there any serious errors in the c functions i added?

Christian Gollwitzer

unread,
Nov 14, 2012, 2:31:25 PM11/14/12
to
Hi,

I had a quick look at your code, but beware that it's hard to find the
error without being able to compile this.

In generally, to find such an error you should compile with -g flag (to
include debug information) and run the program under a debugger. It will
tell you, at which line the program crashed. I don't know about mingw,
in Linux it would be

gdb tclsh
r crash.tcl


Just what I see immediately:
Am 14.11.12 11:57, schrieb Thomas:
> gpc_polygon gpc_polygon_empty_make() {
> gpc_polygon result;
> gpc_vertex_list *list;
remove that line
> result.num_contours = 0;
> result.hole = 0;
> result.contour = list;
that could be result.contour=0;
list is uninitialized memory.
> return result;
> }


> gpc_polygon gpc_polygon_create(gpc_vertex_list *list) {
> gpc_polygon result;
> result.num_contours = 1;
> result.hole = 0;
> result.contour = list;
> return result;
> }
>

A quick look at the code of contour_add suggests, that the hole thing is
a pointer to an array of the hole parameter. This function should
therefore be something like

gpc_polygon gpc_polygon_create(gpc_vertex_list *list, int hole) {
gpc_polygon result;
result.num_contours = 1;
// create an array with one element of type int
result.hole = malloc(sizeof(int));
// assign hole to the first element
result.hole[0]=hole;

result.contour = list;
return result;
}



> double gpc_vertex_get(gpc_vertex_list *list, int n, double *result) {
> if (n < 0 || n >= list->num_vertices) {
> // throw error. This is painful if not using C++
> // so I simply ignore it here
> } else {
> double x=list->vertex[n].x;
> *result=list->vertex[n].y;
> return x;
> }
> }

This function probably does not work as intended. Reason: result is an
output parameter, but SWIG does not know it. It will expect, that you
feed a pointer to a double, which is impossible to construct from Tcl.
What you really want, is that the result is inserted into the list of
results. You can achieve this by calling the parameter OUTPUT instead of
result, or - even better - tell SWIG to apply the OUTPUT rule to the
parameter. Best way would be

--header file ---
#ifdef SWIG
%apply double *OUTPUT {double *x, double *y };
#endif
void gpc_vertex_get(gpc_vertex_list *list, int n, double *x, double *y);
#ifdef SWIG
%clear double *x;
%clear double *y;
#endif

---- c file ---
void gpc_vertex_get(gpc_vertex_list *list, int n, double *x, double *y) {
if (n < 0 || n >= list->num_vertices) {
// throw error. This is painful if not using C++
// so I simply ignore it here
*x=0; *y=0;
} else {
*x=list->vertex[n].x;
*y=list->vertex[n].y;
}
}

--- end ---

This tells SWIG that for the function gpc_vertex_get, it should apply
the output rule for the x and y parameters.

Again, no guarantee for success, as I haven't compiled that code. Next
time you could upload the code so that anybody can try to really compile
that stuff.

Hope this gets you started,

Christian

elfi...@gmail.com

unread,
Nov 19, 2012, 2:28:32 AM11/19/12
to
Hi

sorry for the delay.
here's the stuff i got so far.

it's working quiet well, even tho it might not be perfect.
And i didn't add any credits/licence information yet.

gpc.h
http://pastebin.com/SEkyEvfe
gpc.c
http://pastebin.com/jSYRgfNJ
gpc.i
http://pastebin.com/WNdVfuND
0 new messages