soren.hein has asked for the wisdom of the Perl Monks concerning the following question:

I'm on 64-bit perl 5.14.2 and cygwin on 64-bit Windows 7.

I'm trying to create a simple test case for the following problem, and it's driving me mad. I actually had it working at some point, but I must have changed something that seemed immaterial, and I didn't make a copy...

1. simplelib.c has a pure C function, own_function(), and a header file dll.h. It gets compiled and turned into simplelib.dll.

2. standalone.c links against simplelib.dll and calls own_function(). This works.

3. glue.xs includes dll.h and calls own_function(). Later on, the glue is going to become more complex, but that's the idea.

4. I want to compile glue.xs AND add simplelib.dll into Glue.dll.

5. I want to use Dynaloader from Perl to access Glue.dll through the XS function own_function().

The mechanics work, as long as glue.xs doesn't actually call own_function(). But as soon as I uncomment that one line, the loader complains,

"Can't load lib/Glue.dll for 'Glue::IF': No such file or directory..."

The file does exist, as it's in the same place with the same name. But uncommenting the call to the DLL function own_function() causes the problem.

Here are the files.

simplelib.c

-----------

#include <stdio.h> #include "dll.h" extern "C" int __stdcall own_function(int arg) { printf("Hello from simplelib, arg = %d\n", arg); return 0; }

dll.h

-----

extern "C" int __stdcall own_function(int arg);

Compilation

-----------

g4 -c -I. -I/home/soren.hein/include -DPERL_USE_SAFE_PUTENV -U__STRICT +_ANSI__ -g -fno-strict-aliasing -pipe -fstack-protector -DUSEIMPORTLI +B -O3 "-I/usr/lib/perl5/5.14/i686-cygwin-threads-64int/CORE" simpleli +b.c g4 --shared -Wl,--enable-auto-import -Wl,--export-all-symbols -Wl,--en +able-auto-image-base -L/usr/local/lib -fstack-protector simplelib.o - +o simplelib.dll

standalone.c

------------

#include <stdio.h> #include "dll.h" int main() { int ret; printf("Hello from main\n"); ret = own_function(5); }

Compilation

-----------

g4 -c -I. -I/home/soren.hein/include -DPERL_USE_SAFE_PUTENV -U__STRICT +_ANSI__ -g -fno-strict-aliasing -pipe -fstack-protector -DUSEIMPORTLI +B -O3 "-I/usr/lib/perl5/5.14/i686-cygwin-threads-64int/CORE" standalo +ne.c g4 -Wl,--enable-auto-import -Wl,--export-all-symbols -Wl,--enable-auto +-image-base -L/usr/local/lib -fstack-protector standalone.o -o standa +lone /home/soren.hein/testcase/xs/simplelib.dll

./standalone.exe yields

Hello from main Hello from simplelib, arg = 5

glue.xs

-------

#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "dll.h" MODULE = Glue::IF PACKAGE = Glue::IF PROTOTYPES: ENABLE void own_function(inlist) SV * inlist INIT: int i, ret; PPCODE: printf("Hello from XS\n"); i = 17; ret = own_function(i);

where the last line is either like that, or commented out.

Compilation into Glue.dll

-------------------------

/usr/bin/perl.exe /usr/lib/perl5/5.14/ExtUtils/xsubpp -typemap /usr/li +b/perl5/5.14/ExtUtils/typemap glue.xs > glue.xsc && mv glue.xsc glue. +c g4 -c -I. -I/home/soren.hein/include -DPERL_USE_SAFE_PUTENV -U__STRICT +_ANSI__ -g -fno-strict-aliasing -pipe -fstack-protector -DUSEIMPORTLI +B -O3 "-I/usr/lib/perl5/5.14/i686-cygwin-threads-64int/CORE" glue.c rm -f DDS_IF.dll g4 --shared -Wl,--enable-auto-import -Wl,--export-all-symbols -Wl,--en +able-auto-image-base -L/usr/local/lib -fstack-protector glue.o -o Glu +e.dll /usr/lib/perl5/5.14/i686-cygwin-threads-64int/CORE/cygperl5_14. +dll /home/soren.hein/testcase/xs/simplelib.dll

I'm not showing the Perl to call it all, but it does get to "Hello from XS" with the critical line commented out. With the line enabled, the DLL compiles, but Dynaloader doesn't want to load it anymore. Help!

Replies are listed 'Best First'.
Re: XS with DLL
by Anonymous Monk on Jun 04, 2014 at 22:06 UTC

    The file does exist, as it's in the same place with the same name.

    If you use depends.exe /c /f:1 /pb /ot:temp.txt ... ...\perl.exe ...\foo.pl ... you'll see that Glue.dll is trying to load simplelib.dll and can't find it; simplelib.dll has to be next to Glue.dll or somewhere in %PATH%

    If you had linked againt a static version, someting like simplelib.a, then there would only be Glue.dll

    Help!

    Makefile.PL is standard way to deal with XS; No Makefile.PL (or Build.PL) makes me nervous :)

      Aha, that explains the general problem, many thanks. I think I had a .a file lying around earlier, not thinking it mattered, and that's probably the reason that it worked once at random.

      What I really want to do is to work with a third-party DLL for which I have a dll.h header file and an Exports.def file. I don't have a static version.

      If there's a way to turn this information into a static simplelib.a, then I'm happy to do it. But I can't recompile the third-party DLL. I tried doing what it says at the bottom of https://cygwin.com/cygwin-ug-net/dll.html (dlltool), getting a libsimple.a. I can link standalone.o against this, and even run it, but I get zero output, so something is wrong.

      Please excuse the basic questions (remember, g++ and Cygwin on Windows):

      How exactly do I turn simplelib.dll into a proper libsimple.a?

      How do I link against it stand-alone? I assume ... standalone.o -o standalone -L. -lsimple

      How do I tie libsimple.a and glue.o (the XS .o) together into a proper DLL that is self-contained and can be moved around and loaded by DynaLoader?

      I'm not against MakeMaker, but I couldn't get it to do what I wanted, and it's so big and intransparent that I decided to try to understand the actual steps first.

        What I really want to do is to work with a third-party DLL for which I have a dll.h header file and an Exports.def file. I don't have a static version

        I don't know how you can create a static library with that, but you could create an import library for the dll:
        dlltool --kill-at --input-def your.def --output-lib lib_choose_a_name. +a
        Then you need to link to lib_choose_a_name.a when building the project.
        I don't know how to link the XS code to that import library without using ExtUtils::MakeMaker.

        The dll will still be need to be found at runtime (so it needs to be in the path or the cwd) but the code in the XS file you originally presented should then need no modification - assuming, of course, that "dll.h" contains the declaration of the "own_function" function (and that your dll exports that function).

        Cheers,
        Rob