Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Using Inline::C in a package

by rem45acp (Novice)
on Sep 04, 2013 at 16:45 UTC ( #1052386=perlquestion: print w/ replies, xml ) Need Help??
rem45acp has asked for the wisdom of the Perl Monks concerning the following question:

I need to be able to call some C functions inside a package that I have wrote. I cannot seem to figure out how to embed the C code in a perl package, as all the examples I can find of Inline::C are just plain old scripts. I have been able to properly link to external C libraries and include header files in a normal script and get it working. Here is what I have so far:
package PIC::DevaSysI2CIO; use strict; use Inline C => Config => LIBS => "-LE:/drivers/usb/devasys_i2cio -lusbi2cio", INC => "-IE:/drivers/usb/devasys_i2cio", BUILD_NOISY => 1; use Inline C; sub new { my ($class_name) = @_; my ($self) = {}; bless($self, $class_name); return $self; } sub open_device { h = openDevice(); } 1; __END__ __C__ #include <windows.h> #include "Usbi2cio.h" HANDLE openDevice() { HANDLE h = INVALID_HANDLE_VALUE; h = DAPI_OpenDeviceInstance("UsbI2cio", 0); return h; }
When I test the package in a separate perl script, I get the following: Bareword "C" not allowed while "strict subs" in use at E:/lib/Perl/lib/PIC/DevaSysI2CIO.pm line 7. Compilation failed in require at E:\sandbox\test.pl line 2. BEGIN failed--compilation aborted at E:\sandbox\test.pl line 2. Thank you.

Comment on Using Inline::C in a package
Download Code
Re: Using Inline::C in a package
by choroba (Abbot) on Sep 04, 2013 at 16:53 UTC
    I have no experience with Inline::C, but the following line seems suspicious:
    use Inline C;

    I would say there is a :: missing on line 7.

    Update.
    It works for me if I change it to

    use Inline 'C';

    Note that using the fat comma (=>) automatically quotes the C. This problem only happens under strict.

    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      I would say there is a :: missing on line 7.

      No. The OP is exactly correct. That is how Inline C is used. Though it is normal followd by some other arguments; Eg. This is my standard usage:

      #! perl -slw use strict; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'END_C', NAME => 'rdtsc', CLEAN_AFTER_BUILD => 0; SV *rdtsc() { return newSVuv( (UV)__rdtsc() ); } ... END_C use Data::Dump qw[ pp ]; use GD; ...

      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.
        OK, I stand corrected. Is the repetition of the use line also demanded?
        لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
        So does the C code go before the package declaration? I'm confused on where the perl methods go before or after the C code.

      To clarify why it's "that way":

      You actually are using Inline, with the C plugin. So "C" is an argument passed to Inline similar to how a function name might be specified in an import list.

      The reason it's often seen "bare" is because it's quite common to do it this way:

      use Inline C => 'DATA'; # ... __DATA__ __C__ /* C code here */

      In which case the "C" is actually quoted by the fat comma (=>) operator.

      Multiple uses of Inline C =>... are common and ok; one is often used to specify configuration settings, while others are used to initiate inline code sequences either via a here-doc or the __DATA__ segment.


      Dave

Re: Using Inline::C in a package
by tobyink (Abbot) on Sep 04, 2013 at 17:13 UTC
    use Inline C;

    ... the "C" here is a bareword, so strict 'subs' doesn't like it. You could drop use strict, or you could quote "C" in single or double quotes...

    use Inline 'C';

    ... or use the magic quoting power of the fat comma...

    use Inline C => ();

    Also, I'm pretty sure you want __DATA__ instead of __END__. __END__ behaves the same as __DATA__ in scripts, but not in modules.

    Personally I don't like the __DATA__ loading bit of Inline::C; I just use:

    use Inline C => q{ /* my C code goes here */ };

    (or heredocs).

    PS: a very simple module using Inline::C is Devel::PL_origargv - take a peek at the source code and let me know if you have any questions about it.

    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
      Based on all the responses, this is what I have so far. It gets past the build stage, but it complains about no __DATA__ section, and also cannot find the openDevice() function
      package PIC::DevaSysI2CIO; use strict; use Inline C => Config => LIBS => "-LE:/drivers/usb/devasys_i2cio -lusbi2cio", INC => "-IE:/drivers/usb/devasys_i2cio", BUILD_NOISY => 1; use Inline C => q { #include <windows.h> #include "Usbi2cio.h" HANDLE openDevice() { HANDLE h = INVALID_HANDLE_VALUE; h = DAPI_OpenDeviceInstance("UsbI2cio", 0); return h; } }; sub new { my ($class_name) = @_; my ($self) = {}; bless($self, $class_name); return $self; } sub open_device { my $h = openDevice(); } 1;
Re: Using Inline::C in a package
by BrowserUk (Pope) on Sep 04, 2013 at 17:23 UTC

    Whilst multiple use Inline C => ... lines are common a useful; without the C being followed by a fat comma (=>) the C becomes a prohibited bareword. In any case, that second use line with no arguments is redundant.

    Correct that (ie. remove the redundant line) and you'll find your next error:

    C:\test>perl junk.pm Can't modify constant item in scalar assignment at junk.pm line 19, ne +ar ");"

    Which is this line:

    h = openDevice()

    Variables need sigils in Perl.

    Cccorrect that and you're on your own as I don't have the headers or library to try to compile your c code.


    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.
      I have been able to get it to fully compile.
      It croaks if OpenDevice returns a HANDLE, which is
      typedef void* HANDLE;
      But if OpenDevice returns void everything compiles and runs at least.
      Here is the updated code:
      package PIC::DevaSysI2CIO; use strict; use Inline C => Config => LIBS => "-LE:/drivers/usb/devasys_i2cio -lusbi2cio", INC => "-IE:/drivers/usb/devasys_i2cio", BUILD_NOISY => 1; use Inline C => q { #include <windows.h> #include "Usbi2cio.h" #include <stdio.h> void OpenDevice() { HANDLE handle = INVALID_HANDLE_VALUE; handle = DAPI_OpenDeviceInstance("UsbI2cIo", 0); if (handle == INVALID_HANDLE_VALUE) { printf("Could not open device\n"); } else { printf("Opened device!\n"); } } }; sub new { my ($class_name) = @_; my ($self) = {}; bless($self, $class_name); return $self; } sub open_device { OpenDevice(); } 1;

        You'll need to wrap the C handle in a bless reference. See Re^12: odd line in windows for an example.


        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.

        Hi, rem45acp,

        I suggest you use InlineX::C2XS to get the task done with out any annoyance. first: create a test.pl like below:

        use strict; use Inline C => Config => LIBS => "-LE:/drivers/usb/devasys_i2cio -lusbi2cio", INC => "-IE:/drivers/usb/devasys_i2cio", BUILD_NOISY => 1; use Inline C => q { #include <windows.h> #include "Usbi2cio.h" #include <stdio.h> void OpenDevice() { HANDLE handle = INVALID_HANDLE_VALUE; handle = DAPI_OpenDeviceInstance("UsbI2cIo", 0); if (handle == INVALID_HANDLE_VALUE) { printf("Could not open device\n"); } else { printf("Opened device!\n"); } } };
        then run: c2xs ....... it will produce a XS package for you. Please refer Inline::C2XS doc for details.




        I am trying to improve my English skills, if you see a mistake please feel free to reply or /msg me a correction

Re: Using Inline::C in a package
by syphilis (Canon) on Sep 05, 2013 at 12:26 UTC
    cannot seem to figure out how to embed the C code in a perl package

    Incidentally, you can have multiple packages in the one Inline::C script (just as you can with perl scripts):
    package FOO; use Inline C => <<'EOC'; void hello() { printf("Hello from FOO\n"); } EOC package BAR; use Inline C => <<'EOC'; void hello() { printf("Hello from BAR\n"); } EOC package FUBAR; use Inline C => <<'EOC'; void hello() { printf("Hello from FUBAR\n"); } EOC FOO::hello(); BAR::hello(); FUBAR::hello(); hello();
    Which outputs:
    Hello from FOO Hello from BAR Hello from FUBAR Hello from FUBAR
    Cheers,
    Rob

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1052386]
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (9)
As of 2014-12-25 21:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (163 votes), past polls