in reply to Re^3: Need Help with perlxstut
in thread Need Help with perlxstut

OK, been doing my home work and came across the -MInline=info switch, and this is the result of the command on my little script:

C:\HilbertPL>perl -MInline=info HilbertPL.pl <-----------------------Information Section-----------------------------------> Information about the processing of your Inline C code: Your module is already compiled. It is located at: C:\HilbertPL\_Inline\lib\auto\HilbertPL_pl_301c\HilbertPL_pl_301c.dll The following Inline C function(s) have been successfully bound to Perl: unsigned hilbert_box_pt(unsigned nDims, unsigned nBytes, unsigned nBits, int findMin, void * c1, void * c2) unsigned hilbert_box_vtx(unsigned nDims, unsigned nBytes, unsigned nBits , int findMin, void * c1, void * c2) <-----------------------End of Information Section----------------------------> Had problems bootstrapping Inline module 'HilbertPL_pl_301c' Can't find 'boot_HilbertPL_pl_301c' symbol in C:\HilbertPL\_Inline\lib/auto/Hilb ertPL_pl_301c/HilbertPL_pl_301c.dll at C:/Perl/site/lib/Inline.pm line 500 at HilbertPL.pl line 14 BEGIN failed--compilation aborted at HilbertPL.pl line 1076.

I understand now that I probably have a typing issue, but where to start? There is a lot of c code with which I am not familiar, and I cringe at adjusting it too much for fear of breaking it, but here is what I do know:
There are only 8 functions defined in hilbert.h and here are their signatures:
/***************************************************************** * hilbert_i2c * * Convert an index into a Hilbert curve to a set of coordinates. * Inputs: * nDims: Number of coordinate axes. * nBits: Number of bits per axis. * index: The index, contains nDims*nBits bits (so nDims*nBits m +ust be <= 8*sizeof(bitmask_t)). * Outputs: * coord: The list of nDims coordinates, each with nBits bits. * Assumptions: * nDims*nBits <= (sizeof index) * (bits_per_byte) */ void hilbert_i2c(unsigned nDims, unsigned nBits, bitmask_t index, bitm +ask_t coord[]); /***************************************************************** * hilbert_c2i * * Convert coordinates of a point on a Hilbert curve to its index. * Inputs: * nDims: Number of coordinates. * nBits: Number of bits/coordinate. * coord: Array of n nBits-bit coordinates. * Outputs: * index: Output index value. nDims*nBits bits. * Assumptions: * nDims*nBits <= (sizeof bitmask_t) * (bits_per_byte) */ bitmask_t hilbert_c2i(unsigned nDims, unsigned nBits, bitmask_t const +coord[]); /***************************************************************** * hilbert_cmp, hilbert_ieee_cmp * * Determine which of two points lies further along the Hilbert curve * Inputs: * nDims: Number of coordinates. * nBytes: Number of bytes of storage/coordinate (hilbert_cmp onl +y) * nBits: Number of bits/coordinate. (hilbert_cmp only) * coord1: Array of nDims nBytes-byte coordinates (or doubles for + ieee_cmp). * coord2: Array of nDims nBytes-byte coordinates (or doubles for + ieee_cmp). * Return value: * -1, 0, or 1 according to whether coord1<coord2, coord1==coord2, coord1>coord2 * Assumptions: * nBits <= (sizeof bitmask_t) * (bits_per_byte) */ int hilbert_cmp(unsigned nDims, unsigned nBytes, unsigned nBits, void +const* coord1, void const* coord2); int hilbert_ieee_cmp(unsigned nDims, double const* coord1, double cons +t* coord2); /***************************************************************** * hilbert_box_vtx * * Determine the first or last vertex of a box to lie on a Hilbert cur +ve * Inputs: * nDims: Number of coordinates. * nBytes: Number of bytes/coordinate. * nBits: Number of bits/coordinate. (hilbert_cmp only) * findMin: Is it the least vertex sought? * coord1: Array of nDims nBytes-byte coordinates - one corner of + box * coord2: Array of nDims nBytes-byte coordinates - opposite corn +er * Output: * c1 and c2 modified to refer to selected corner * value returned is log2 of size of largest power-of-two-aligned + box that * contains the selected corner and no other corners * Assumptions: * nBits <= (sizeof bitmask_t) * (bits_per_byte) */ unsigned hilbert_box_vtx(unsigned nDims, unsigned nBytes, unsigned nBits, int findMin, void* c1, void* c2); unsigned hilbert_ieee_box_vtx(unsigned nDims, int findMin, double* c1, double* c2); /***************************************************************** * hilbert_box_pt * * Determine the first or last point of a box to lie on a Hilbert curv +e * Inputs: * nDims: Number of coordinates. * nBytes: Number of bytes/coordinate. * nBits: Number of bits/coordinate. * findMin: Is it the least vertex sought? * coord1: Array of nDims nBytes-byte coordinates - one corner of + box * coord2: Array of nDims nBytes-byte coordinates - opposite corn +er * Output: * c1 and c2 modified to refer to least point * Assumptions: * nBits <= (sizeof bitmask_t) * (bits_per_byte) */ unsigned hilbert_box_pt(unsigned nDims, unsigned nBytes, unsigned nBits, int findMin, void* coord1, void* coord2); unsigned hilbert_ieee_box_pt(unsigned nDims, int findMin, double* c1, double* c2); /***************************************************************** * hilbert_nextinbox * * Determine the first point of a box after a given point to lie on a +Hilbert curve * Inputs: * nDims: Number of coordinates. * nBytes: Number of bytes/coordinate. * nBits: Number of bits/coordinate. * findPrev: Is the previous point sought? * coord1: Array of nDims nBytes-byte coordinates - one corner of + box * coord2: Array of nDims nBytes-byte coordinates - opposite corn +er * point: Array of nDims nBytes-byte coordinates - lower bound o +n point returned * * Output: if returns 1: * c1 and c2 modified to refer to least point after "point" in bo +x else returns 0: arguments unchanged; "point" is beyond the last point of the b +ox * Assumptions: * nBits <= (sizeof bitmask_t) * (bits_per_byte) */ int hilbert_nextinbox(unsigned nDims, unsigned nBytes, unsigned nBits, int findPrev, void* coord1, void* coord2, void const* point); /***************************************************************** * hilbert_incr * * Advance from one point to its successor on a Hilbert curve * Inputs: * nDims: Number of coordinates. * nBits: Number of bits/coordinate. * coord: Array of nDims nBits-bit coordinates. * Output: * coord: Next point on Hilbert curve * Assumptions: * nBits <= (sizeof bitmask_t) * (bits_per_byte) */ void hilbert_incr(unsigned nDims, unsigned nBits, bitmask_t coord[]);

there are also two typedefinitions at the top of the file:
/* define the bitmask_t type as an integer of sufficient size */ typedef unsigned long bitmask_t; /* define the halfmask_t type as an integer of 1/2 the size of bitmask +_t */ typedef unsigned long halfmask_t;

now that is just the header file. The implementation in the .c file is huge. Where would I start to find out what types PERl can't handle or vice versa since I am calling the functions from perl.? Where will this adjustment take place? In the perl script, or will I have to write a tydef file like the xstut shows on one example? Lastly, where do people talk about this stuff? I can't imagine that stuff like this is uncommon, yet it is a pain to find good help on it... Thanks Ketema

Replies are listed 'Best First'.
Re^5: Need Help with perlxstut
by tachyon (Chancellor) on Sep 29, 2004 at 00:23 UTC

    The Inline C docs tell you what types are supported natively (for conversion). You can handle any type you like but since you can define an infinite number......

    You have several issues. First you don't seem to understand typing properly (based on assigning floats to integers in the C++ example above). You also don't seem to understand what header files are for. This is pretty basic stuff and makes it hard to know where to start.

    So what's a header for. Well first you don't need one. All the code can be in the main.c All the code can be in the header.h for that matter. To really understand headers you need to understand types and functions and how compilers work. We declare types using typdef statements for our convenience. Rather than write unsigned long long we might use a typdef to alias that to uint64. The preprocessor effectively does a search and replace, replacing every instance of uint64 with 'unsigned long long' which is a type the compiler understands. The function declarations in the header help the compiler. Under the covers when you call a function this is what happens (simplified). The arguments to the function are pushed onto the stack. The compiler knows how much space it need because an int will take 4 bytes, a short 2 bytes, a char 1 byte, a pointer 4 bytes, etc. The memory address of the instruction following the function call is also pushed onto the stack (so we know where to return to). Last of all control of execution passed to the entry point (first instruction) of the function. The function will strip it arguments off the stack, do its stuff, push its return value onto the stack, and then return control of execution to the return location (the instruction following the function call). In order for the compiler to put together the necessary code it needs to know what arguments a function takes and what it returns. By declaring the functions as prototypes in the header file you avoid issues with code like:

    int func1 ( int a ) { return func2( a ); } int func2 ( int b ) { return b*b; }

    In this code the compiler gets to func1, sees the call to func2 but does not know how to handle it. By declaring the functions in the header you avoid compile errors like this. The header declaration must be exactly the same as the real function. All you need to do is cut and paste the function call up to the opening curly and add a ;

    A header file lets you declare a function. At the compiler level that is essentially just an argument list, return type and and *entry point*. The entry point is where the actualy code that does the stuff lives. You can compile C without having this code present. For example take stdio.h You can find stdio.h but you won't find stdio.c So how does that work. The compiled binary code that actually does the stdio stuff is found in stdlibc (cc and gcc on *nix) or msvcrt (cl.exe on win32). When you compile your code you get an object file. To make it work it is linked to the C library code that actually implements the functions. Linking can be static in which case the relevant binary code from the library is actually stuck into your final executable of dynamic in which case it it not. With dynamic linking you depend on the fact that the stdlib functions will be found at runtime. These are the .lib and .dll files on Win32.

    Anyway Inline will give you the .al error if it can't do the type conversion automatically. The header declaration 'unsigned varname' is shorthand for 'unsigned int varname' where the 'int' declaration is implicit. Inline may of may not cope with that. If as you said you only included the main.c code then there is an obvious problem. In this code there will be lots of bitmask_t types, but without the header the compiler has no idea what that is.

    Handling the bitmask_t coord[] pointer and its conversion will be your main issue. There are several ways to do it, including the one I showed you before.

    It is not that hard. I suggest getting just one function working to start. Rinse and repeat.

    cheers

    tachyon