Thanks. I think this module will help greatly, and I think i'm going to pick up Advanced Perl Programming to get better at the "traditional" way. Should have know there was a module for this though...duh
Thanks Again. | [reply] |
Thank You, I saw that Advanced was published 1997, but I figured since they hadn't revised it that it was still valid. I'll check out your suggestions as well.
| [reply] |
@Coord[3];
hilbert_i2c(3,10,190355,@Coord);
print join(" ",@Coord);
@Coord[2] = 35.5;
@Coord[1] = 40;
@Coord[0] = 36.8;
print hilbert_c2i(3,10,@Coord), "\n";
use Inline C => Config =>
LIBS => '-lhilbert';
use Inline C => <<'END_OF_C_CODE';
Lots of C code Here with the above functions implemented
END_OF_C_CODE
The script chugs along, then errors out on the compile with the following:
E:\Profiles\ADMINI~1.TEM\MYDOCU~1\VISUAL~1\MACHIN~1>perl Hilbertknn.pl
Can't locate auto/main/hilbert_i2c.al in @INC (@INC contains: E:\Profi
+les\ADMINI
~1.TEM\MYDOCU~1\VISUAL~1\MACHIN~1\_Inline\lib E:/Perl/lib E:/Perl/site
+/lib .) at
Hilbertknn.pl line 2
"Can't locate auto/main/hilbert_i2c.al in @INC" being the most relevant part obviously, but I am at a loss as to where the proper files should be. The hilbert.c file is in the inline portion of the perl script, and the Hilbert.h files is in the same directory. Where else should it go? | [reply] [d/l] [select] |
When you say it chugs along what you mean is that it fails to compile. For a start your calling syntax is just not going to work. Next your knowledge of C seems imperfect. A library is compiled binary code. To use it you need the headers and the library. You don't have that, you have the C headers and main source code. If you are goind to inline it you need the headers and then the main source inline.
When you want to link C code into Perl the main issue is basically type conversion, from the perl SV, AV or HV types, into C types and then back again. The main advantage of Inline::C is it will handle some simple type conversions for you automatically, but it only handles really simple ones. With XS you are expected to do it yourself.
Your error will probably be typemap/conversion related. You will also need to pass an array ref of your N dimensional coordinates and decant the values in your C. See Re: Using c executable in Perl Script for an example of how to do that.
| [reply] |
All I have is a hilbert.c file and an hilbert.h file Provided to me, I didn't write it. Off third party information I was told the .c file implements the functions defined in the .h file. Together they are about 2700 or so lines of code.
The error specifically says "Can't locate auto/main/hilbert_i2c.al" That is a file I'm assuming is generated by the Inline module, but I don't know. The examples I have found don't come any where close to the length or complexity of the two c files I have. I have a book on its way called Extending and Embedding PERL, but until that gets here I need to know what you mean by: "To use it you need the headers and the library" Does that mean both c files should appear between in the section for code of the Inline modlue? If so that is not very apparent, because most of the examples have a few lines of code in which .h files are #included. by the way, I know the two c files work, because I made a simple C++ executable using them and they spit out hilbert indexes and return co-ordinates just fine
#include <stdio.h>
#include <iostream>
#include "hilbert.h"
using namespace std;
int main()
{
unsigned long Coord[3];
hilbert_i2c(3,10,190355,Coord);
cout << Coord[2] << ',' << Coord[1] << ',' << Coord[0] << endl;
Coord[2] = 35.5;
Coord[1] = 40;
Coord[0] = 36.8;
cout << hilbert_c2i(3,10,Coord) << endl;
return 0;
}
| [reply] [d/l] |
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
| [reply] [d/l] [select] |
Well i think I figured out the steps I'm going to take. I found a great site http://www.steve.gb.com/perl/lesson14.html and i believe the solution for me will be to break up my hilbert.c file and take it function by function and make sure that the definitions correctly match PERL datatypes. I have printed out perlapi and perl guts and hopefully will be successfull. I wonder if the hilbert.h file has to be adjusted too? It sucks that you can't just cut and paste, that would be really cool!, but I'm not above trudging through it, just going to take a while......
| [reply] |