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

I have installed and successfully tested Inline::C with a simple "Hello World" and vowel counter (from the Inline::C Cookbook) so I'm reasonably happy that the installation is correct. I now want to invoke a vendor's C written API from Perl. The vendor's sample C code includes the line: #define SHLIBNAME “dptcpiphi.dll” My Perl code includes the following in order to access (I pray) the functions which I expect to be contained in dptcpiphi.dll:
use Inline C => Config => AUTO_WRAP => ENABLE; use Inline C => Config => LIBS => '-L"C:\Program Files\Common Files\Pr +oduct\4.1\dptcpiphi.dll" -ldptcpip';
The full Perl script is short:
#!/usr/bin/perl -w use Inline C => Config => AUTO_WRAP => ENABLE; use Inline C => Config => LIBS => '-L"C:\Program Files\Common Files\Pr +oduct\4.1\dptcpiphi.dll" -ldptcpip'; use Inline C => DATA ; use strict; my $DPbuff = "statusbuffer"; my $status = MyGetCtrlStatus('0x14','localhost','1703',$DPbuff); print "$status\n"; __END__ __C__ int MyGetCtrlStatus(char ShiftCmd, char pHostName, char uPortNum, char + pCtrlStatus) { char JobInfo; int status = DPGetCtrlStatus(ShiftCmd, pHostName, uPortNum, pCtrlS +tatus); printf ("Running...\n"); return pHostName; }
The gcc compile step appears to complete successfully but when it comes time to link the object libraries together it fails:
Test_pl_5261.o:Test_pl_5261.c:(.text+0x27): undefined reference to `DP +GetCtrlStatus' collect2: ld returned 1 exit status dmake.exe: Error code 129, while making 'blib\arch\auto\Test_pl_5261\ +Test_pl_5261.dll'
(I know the code isn't going to work at present but I can fix that as long as I can get Inline::C to link the vendor libraries into my Perl script.) Have I completely misinterpreted the purpose and capabilities of Include::C or simply made a mess of using the tool?

Replies are listed 'Best First'.
Re: Understanding Inline::C to call vendor libraries
by syphilis (Archbishop) on Jul 25, 2014 at 13:08 UTC
    undefined reference to `DPGetCtrlStatus'

    Is there an import lib (.a or .lib file) for the dll ? If so - what is its name and where is it located ?
    With that information, we can fix it so that we link to that library and resolve the undefined reference.

    If you have only the dll, then (IIRC) with gcc you should be able to link directly to it using the MYEXTLIB config option:
    use Inline C => Config => MYEXTLIB => 'C:/Program Files/Common Files/P +roduct/4.1/dptcpiphi.dll'
    (I'm assuming that's the fully qualified path name of the dll.)

    If that still doesn't resolve the undefined reference then we'll have to come up with something else.
    There are other options such as creating the import library, or loading the dll with LoadLibrary - but see how you go with the above suggestions first.

    Cheers,
    Rob
      Thanks for your perserverance Rob. There's only the dll file. I've tried various permutations and combinations of Config statements and I've moved the dll file into the same folder as my Perl code to try to eliminate path issues. I need inspiration!
        I've moved the dll file into the same folder as my Perl code to try to eliminate path issues

        It's better to put it in a folder that's already in the path, or add the location of the dll to the path:
        set PATH=C:\wherever\it\is;%PATH%
        At least then you know that it's going to be found when needed. (And if something wants to load it, but can't find it, you should get a pop-up that tells you quite clearly that the dll could not be found).

        Of course, *I* don't even know whether your dll exports the symbol in question. (Try running objdump -t dptcpiphi.dll >dump.txt 2>&1, then examine dump.txt to see what is being exported.)

        Probably best, anyway, that you create an import library and link to that:
        gendef dptcpiphi.dll dlltool --kill-at --input-def dptcpiphi.def --output-lib libdptcpiphi. +a
        You should already have dlltool (in MinGW/bin), but you probably won't have gendef.
        I know it comes with latest StrawberryPerl. If you want to get hold of it that way then I recommend either this 32-bit build or this64-bit build
        You'll want the same architecture (ie 32 or 64 bit) as the dll itself.
        Just unzip the Strawberry Perl package to whatever location you choose, navigate to that location, double click on 'portableshell.bat' and use the shell that pops up.
        You can probably get gendef elsewhere if you want to hunt around - and I think there's an alternative tool (whose name I can't remember).

        IMHO, you're better off using Strawberry Perl (which ships with gcc-4.8.2) - as opposed to using ActivePerl and gcc-3.4.5. You could, of course, instead use Strawberry's gcc-4.8.2 with ActivePerl, but I think you're better off with Strawberry Perl anyway (unless you're wanting to use a Microsoft compiler).

        Having created the import library, stick it in some location - say C:/my/libs. The correct invocation in the script is then:
        use Inline C => Config => LIBS => '-LC:/my/libs -ldptcpiphi';
        If that doesn't find the missing reference, then the dll apparently doesn't provide it.
        Let us know how you get on.

        Cheers,
        Rob
Re: Understanding Inline::C to call vendor libraries
by Anonymous Monk on Jul 25, 2014 at 07:45 UTC