Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Re^9: Inline::C and NULL pointers

by Marshall (Canon)
on Dec 21, 2021 at 06:18 UTC ( [id://11139789]=note: print w/replies, xml ) Need Help??


in reply to Re^8: Inline::C and NULL pointers
in thread Inline::C and NULL pointers

Rob, I am glad that other Monks jumped in on this.

I agree with this: I'm not convinced that the need to pass NULL pointers from perl to C functions is all that common.

As I mentioned in previous posts, the OP is confronted with some poorly written C code that he can't change. This NULL pointer idea arises from an I/F that says: "if you give a pointer to memory, I will use that memory for output, assuming without question that you have given me enough memory for my yet to be generated output. If you don't give me such a pointer, I will give you a pointer to my non-thread-safe non-recursion-safe static memory." This is a bullshit I/F. But the OP can't change that.

NULL as the 2nd param is a weird situation. If there could be one arg and an optional second arg, then normally this would be implemented with a variable number of args - you don't put NULL, for that second arg - it is simply not there at all for the caller. This of course requires different C code than what the OP is dealing with. printf() for example uses a variable number of arguments.

I did have fun with Inline::C and found it to be "easy to use" for all the "heavy lifting" that is does.

Replies are listed 'Best First'.
Re^10: Inline::C and NULL pointers
by etj (Deacon) on Dec 21, 2021 at 14:52 UTC
    In general C programming, one doesn't have optional arguments. And generally, being able to give a pointer value that is clearly not intended as valid (a NULL) is a valuable thing. That maps very nicely for a Perl interface, to turning an undef input (or, conceivably, no input at all) into a NULL in C terms.

    tl;dr: C and Perl have different idioms, and while XS should probably take an SV* and treat it idiomatically, actual C has different needs.

      Yes, you are correct in that in general, C programming doesn't use optional arguments! I know how to do it, but I can't remember any production code that I've written that uses that idea - a much more normal way is to explicitly pass a single pointer to an array of variable length.

      Again, what is bizarre about this I/F is that it returns a pointer. But sometimes that pointer is to internal static memory and sometimes that pointer is to the memory that you just gave the I/F! In the first case, you had better use that info right away or make your own copy of it for later use - this idea is also non-thread-safe and non-reentrant. To fix that problem, I would dynamically allocate memory for the result and return a pointer to that. If we go with option 2, then the user is responsible for allocating and passing a pointer to enough memory for the result. The problem here is that the sub doesn't know how big of a buffer you have given it. And in general the guy who produces the result is in a much better position to estimate the size of the result than the caller. It is unusual to say the least for option 1 and option 2 to both be available depending upon the calling parms.

      Back to Perl. When was the last time you saw an I/F like this? If I pass the sub a reference for the output, say \$output, I would expect that result goes into my $output and the sub perhaps returns some success or failure code. More likely is that the sub returns an array, a scalar or a reference to an array and perhaps undef on failure. I can't think of a Perl I/F where I am required to pass a reference to an output structure in all cases and undef when I don't want the sub to use that reference for output when instead I want to look for the output as the return value. There is usually one way to give the input and one way to get the output. subs that transform data via a reference to an input. structure are quite common.

      Back to C. Memory allocation in C is a major issue and the source of many, many bugs. Ambiguity about who is allocating memory and who is responsible for it after allocation is "a big deal".

        I don't know why you replied to my point about C with your thoughts about Perl interfaces, but thanks. In Perl there are many options, including returning a list of results (with a result status as first entry), or a hash-ref with a "status" member.

        In C, dealing with memory management is important. One can document who is responsible for deallocating data whose pointer is returned. Another option, used in recent PDL, is to return a pdl_error struct that has as members:

        • an integer for the error type (including none)
        • a char * pointer for any error text
        • a flag saying whether that char * would need freeing after use (so if the string needed sprintf-ing and therefore first malloc-ing, that works without memory leaks)
        Easy, and seems to have no problems so far (except thread-safe realloc for error-accumulation in Windows, but that was straightforward given previous work in PDL on that).

        Parenthetically, the idea behind that is so that all PDL functions can return these thingies on error, instead of using a C-level exception mechanism. That means the PDL C library can start being used in other C-language applications, or have an interface for other dynamic languages.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11139789]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (2)
As of 2024-04-19 18:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found