http://qs321.pair.com?node_id=1169301

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

I'm trying to use Inline::C to wrap around a C library that I've written, and am looking for assistance on the proper approach to include this C code inside of a Perl script. I'm not a C dev, so I may have terminology etc wrong while I'm trying to describe things. To build the library and the ensuing binary, I do this (note that the tempmon.c code is separate from the dht11.c code I'm including in the Perl script):

cc -c -o dhtll.o dht11.c cc -o tempmon tempmon.c dht11.o -l wiringPi

When I put the C code in my test Perl script with:

use strict; use warnings; use Inline 'C';

...I get:

perl: symbol lookup error: /home/pi/repos/scripts/c/rpi/dht11/library/ +_Inline/lib/auto/perl_pl_96d1/perl_pl_96d1.so: undefined symbol: pinM +ode

I'm sure this is because I'm not linking to wiringPi which I do on the command line. wiringPi contains the pinMode() amongst other functions.

When I try to change the ccflags per the documentation:

use Config; my $ccflags .= $Config{ccflags} . " -l wiringPi"; use Inline ('C' => 'END', ccflags => $ccflags);

I get a great big long error that I'm not experienced enough to understand, but it looks like it's missing prototypes, which leads me to believe that it's still not linking something properly. Here's a snip:

Running Mkbootstrap for perl_pl_b1a3 () chmod 644 "perl_pl_b1a3.bs" "/home/pi/perl5/perlbrew/perls/perl-5.24.0/bin/perl" "/home/pi/perl5/p +erlbrew/perls/perl-5.24.0/lib/5.24.0/ExtUtils/xsubpp" -typemap "/hom +e/pi/perl5/perlbrew/perls/perl-5.24.0/lib/5.24.0/ExtUtils/typemap" +perl_pl_b1a3.xs > perl_pl_b1a3.xsc && mv perl_pl_b1a3.xsc perl_pl_b1a +3.c cc -c -I"/home/pi/repos/scripts/c/rpi/dht11/library" -fwrapv -fno-str +ict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_L +ARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -O2 -DVE +RSION=\"0.00\" -DXS_VERSION=\"0.00\" -fPIC "-I/home/pi/perl5/perlbrew +/perls/perl-5.24.0/lib/5.24.0/armv7l-linux/CORE" perl_pl_b1a3.c In file included from perl_pl_b1a3.xs:3:0: /home/pi/perl5/perlbrew/perls/perl-5.24.0/lib/5.24.0/armv7l-linux/CORE +/XSUB.h:142:31: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute_ +_’ before ‘void’ # define XS_EXTERNAL(name) void name(pTHX_ CV* cv __attribute__unu +sed__) ^ perl_pl_b1a3.c:163:1: note: in expansion of macro ‘XS_EXTERNAL’ XS_EXTERNAL(boot_perl_pl_b1a3); /* prototype to pass -Wmissing-protot +ypes */ ^ Makefile:331: recipe for target 'perl_pl_b1a3.o' failed

Here's the full code. Some of it was harvested from elsewhere, other parts are mine. I'm not a C coder, so the code is probably less than desirable. This is just a test:

use warnings; use strict; use Config; my $ccflags .= $Config{ccflags} . " -l wiringPi"; use Inline ('C' => 'END', ccflags => $ccflags); #use Inline 'C'; my $dht_pin = 4; my $err_pin = 1; my $temp_limit = 65.0; my $warn_pin = 6; my $ret = read_temp($dht_pin, $err_pin, $temp_limit, $warn_pin); print "$ret\n"; cleanup($dht_pin, $err_pin, $warn_pin); __END__ __C__ #include <wiringPi.h> #include "dht11.h" #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> #define MAXTIMINGS 85 float read_temp(int dhtPin, int tempErrPin, float tempErrLimit, int te +mpWarnPin) { int dht11_dat[5] = { 0, 0, 0, 0, 0 }; uint8_t laststate = HIGH; uint8_t counter = 0; uint8_t j = 0, i; float f; /* fahrenheit */ dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_ +dat[4] = 0; /* pull pin down for 18 milliseconds */ pinMode(dhtPin, OUTPUT); digitalWrite(dhtPin, LOW ); delay( 18 ); /* then pull it up for 40 microseconds */ digitalWrite(dhtPin, HIGH ); delayMicroseconds( 40 ); /* prepare to read the pin */ pinMode(dhtPin, INPUT ); /* detect change and read data */ for ( i = 0; i < MAXTIMINGS; i++ ) { counter = 0; while ( digitalRead( dhtPin ) == laststate ) { counter++; delayMicroseconds( 1 ); if ( counter == 255 ) { break; } } laststate = digitalRead( dhtPin ); if ( counter == 255 ) break; /* ignore first 3 transitions */ if ( (i >= 4) && (i % 2 == 0) ) { /* shove each bit into the storage bytes */ dht11_dat[j / 8] <<= 1; if ( counter > 16 ) dht11_dat[j / 8] |= 1; j++; } } /* * check we read 40 bits (8bit x 5 ) + verify checksum in the last + byte * print it out if data is good */ if ( (j >= 40) && (dht11_dat[4] == ( (dht11_dat[0] + dht11_dat[1] + dht11_dat[2 +] + dht11_dat[3]) & 0xFF) ) ) { f = dht11_dat[2] * 9. / 5. + 32; // debugging // printf("f: %.1f: warn: %.1f\n", f, tempErrLimit); // printf("warnPin: %d\n", tempWarnPin); int warn = 0; if (tempErrPin > -1) { pinMode(tempErrPin, OUTPUT); if (f > tempErrLimit) { warn = 1; digitalWrite(tempErrPin, HIGH); if (tempWarnPin > -1) { pinMode(tempWarnPin, OUTPUT); digitalWrite(tempWarnPin, HIGH); } } else { digitalWrite(tempErrPin, LOW); } } /* * printf( "Humidity = %d.%d %% Temperature = %d.%d *C (%.1f * +F)\n", * dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3], f ) +; */ if (warn > 0) { return f; } else { return 0.0; } } } int cleanup(int dhtPin, int tempErrPin, int tempWarnPin) { digitalWrite(dhtPin, LOW); pinMode(dhtPin, INPUT); digitalWrite(tempErrPin, LOW); pinMode(tempErrPin, INPUT); digitalWrite(tempWarnPin, LOW); pinMode(tempWarnPin, INPUT); return(0); }