ajaffres has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I have written a dynamic library in c in which I have some functions of this kind:

int MyFunction(unsigned char *input, unsigend char *output); where input is a pointer to an unsigned char which holds the content of a binary file. Therefore I can't treat it as a pointer to a string (because of the '\0') in which case I may lose some data.
output is as well a pointer to an unsigned char (not a NULL terminated string either).

Now, I would like to call such functions from a Perl program. I am using SWIG in order to wrap these library functions. However, since SWIG can't do the job 100% right, the 'unsigned char *' type is not treated properly. As far as I know, there is a way to overcome this problem, which is (maybe among different methods) to use 'typemap'.

My question: How can I use 'typemap' so that I can receive and return through my function's arguments 'pointers to unsigned char' (or to a string if you prefer) preferably without passing the length of the string? (I found some converstion functions such as SvPV and sv_setpv, but I am not sure that they do exactly what I want). I would like if it possible to make no change at all to my c functions.

Thanks very much for your help ( I am new to Perl and to SWIG)...

Arnaud

Replies are listed 'Best First'.
Re: Calling c functions from perl...
by demerphq (Chancellor) on May 18, 2005 at 14:30 UTC

    My suggestion would be to jettison SWIG. Of course I dont have any experience with SWIG but I do have experience with Inline::C so this isn't coming from an unbiased viewpoint. :-)

    Anyway, Inline::C will automatically wrap most C functions with the appropriate XS glue. Occasionally it needs help with special typemaps but not often. Besides that constructing an SV with the appropriate properties is quite easy, but you will need to know the length of the buffer and the utilized part of the buffer for it to work. IMO you should immediately go an download Inline::C and play with it. It is not difficult to use at all, and probably will help you design a Perl/C interface layer for your code much easier than SWIG will.

    ---
    $world=~s/war/peace/g

      I know both Inline::C and SWIG (and BTW, XS) and using SWIG is not more difficult than Inline::C.

      The real problem with SWIG is that the Perl module is not very well maintained :-(

        Well, Inline::C is well maintained. And given how totally easy it is to use and the questions the OP was giving in the CB it seems to me to be a better starting place for understanding how the whole C/Perl interfacing thing works. To me I::C is a just a tool to produce XS with minimal pain. Pain it seems that the OP is encountering with SWIG. :-)

        ---
        $world=~s/war/peace/g

Re: Calling c functions from perl...
by Tanktalus (Canon) on May 18, 2005 at 15:12 UTC

    <lang mode="C">I'm kind of curious - without the nul terminator, how does your C code know the length of input, or the length of the output, for that matter? I would have to think that you would need size_t's for the sizes of the buffers.</lang>

      The length is worked out withing the functions. I want to pass the a pointer only (not the whole array). I hope to create either an array or a string in perl and to pass the address of the array/string to the functions. Therefore, there is no need to pass the length.
        SWIG will handle the input parameter for you without any typemap, but for the output parameter you need a way to get its length in order to convert it back to an SV and a typemapto do so.

        Look for perl5/typemaps.i in the SWIG Lib directory, you will find there some samples of how to handle output parameters... just grep for OUTPUT.