http://www.perlmonks.org?node_id=1052553


in reply to Re^3: Using Inline::C in a package
in thread Using Inline::C in a package

You'll need to wrap the C handle in a bless reference

Actually, I think you can just return the HANDLE to perl with newSVuv().
I certainly have a script that passes a HANDLE between perl and C (in both directions) as a UV, and it works fine:
use warnings; use strict; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'EOC'; SV * get_handle() { return newSVuv(GetStdHandle(STD_OUTPUT_HANDLE)); } SV * get_attr(SV * h) { CONSOLE_SCREEN_BUFFER_INFO Info; if(!GetConsoleScreenBufferInfo((HANDLE)SvUV(h), &Info)) croak("Error obtaining current attributes"); return newSVuv(Info.wAttributes); } void set_attr(SV * h, SV * attr) { if(!SetConsoleTextAttribute((HANDLE)SvUV(h), (WORD)SvUV(attr))) croak("Error setting attributes"); } EOC use constant { FOREGROUND_BLUE => 1, FOREGROUND_GREEN => 2, FOREGROUND_RED => 4, FOREGROUND_INTENSITY => 8, BACKGROUND_BLUE => 16, BACKGROUND_GREEN => 32, BACKGROUND_RED => 64, BACKGROUND_INTENSITY => 128}; $| = 1; my $h = get_handle(); my $current = get_attr($h); my $current_background = $current & (BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY); # $current_foreground not needed in this script my $current_foreground = $current & (FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); # Set $message to intense red on current background my $message = FOREGROUND_RED | FOREGROUND_INTENSITY | $current_background; set_attr($h, $message); print "ERROR_MSG = xyz"; # Restore original foreground/background colours. set_attr($h, $current); print "\n All Done\n";

(On Windows, that script just prints "ERROR_MSG = xyz" in bold red, then "All Done" in the original console color.)

So ... for the OP, I'm thinking if it's desired that OpenDevice() returns the handle, then it just needs to be:
SV * OpenDevice() { HANDLE handle; /* Do stuff that creates the handle */ return newSVuv(handle);
And to pass that handle from perl back to C:
void pass_handle(SV * handle) { HANDLE h = (HANDLE)SvUV(handle); /* Do stuff with the handle */ }
Alternatively, it can be passed around just as well as an unsigned long:
unsigned long OpenDevice() { HANDLE handle; /* Do stuff that creates the handle */ return (unsigned long)handle;
And to pass that handle from perl back to C:
void pass_handle(unsigned long handle) { HANDLE h = (HANDLE)handle; /* Do stuff with the handle */ }

That seems to be all that's needed - for any HANDLEs I've passed around, at least.

Cheers,
Rob

Replies are listed 'Best First'.
Re^5: Using Inline::C in a package
by BrowserUk (Patriarch) on Sep 05, 2013 at 12:30 UTC
    That seems to be all that's needed - for any HANDLEs I've passed around, at least.

    Yes. I've done that too. The problem that arose was that if I did anything to the value in Perl that caused perl to look at it as anything other than an unsigned integer, and by the time that value got back to the C code it could be corrupted.

    From memory, the first time was a quick debug statement something like:

    print 'Before call: '. $handle;

    Notice the accidental '.' instead of ','. That caused the handle to be converted to the string representation of itself, and by the time it got back to the c code and was converted back from string to number, it was corrupted.

    I forget the exact details -- it was a while ago -- but from memory, the (32-bit) unsigned value was greater 2**31-1, so the default string representation took on a minus sign. When converting back it went through a signed integer before being cast to an unsigned integer and that screwed it.

    Another problem is portability. In 32-bit, void* is a 32-bit unsigned integer; On 64-bit, a 64-bit value.

    And cross-platform, aren't unsigned long different sizes on 64-bit *nix and Windows? (Or is that the long long type.) See this from wikipedia:

    Many 64-bit compilers today use the LP64 model (including Solaris, AIX, HP-UX, Linux, OS X, BSD, and IBM z/OS native compilers). Microsoft's Visual C++ compiler uses the LLP64 model. The disadvantage of the LP64 model is that storing a long into an int may overflow. On the other hand, casting a pointer to a long will work. In the LLP model, the reverse is true. These are not problems which affect fully standard-compliant code, but code is often written with implicit assumptions about the widths of integer types.

    And then there is the (somewhat cockeyed) reasoning MS use the "opaque" void * for things that are not pointers.

    In general, I've found it best to (try to) keep values that originate from C/system libraries, well clear of anywhere Perl can try and manipulate them. Because whilst it works 99% of the time; tracking down the 1% is hell on earth :)


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      if I did anything to the value in Perl that caused perl to look at it as anything other than an unsigned integer, and by the time that value got back to the C code it could be corrupted

      Yes, that would not be nice :-(

      aren't unsigned long different sizes on 64-bit *nix and Windows?

      I think that's generally (perhaps universally) so. I do know that the long type on my 64-bit Ubuntu box is 64 bits, but 32-bits on 64-bit Windows.
      This is not so much of a consideration as regards Windows HANDLEs specifically, but is of relevance in general.

      Cheers,
      Rob
        This is not so much of a consideration as regards Windows HANDLEs specifically ...

        Of course. Silly me :)


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.