Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Errors using DLL from Inline C with 32-bit Perl

by vr (Curate)
on Jan 29, 2020 at 13:28 UTC ( [id://11112009]=perlquestion: print w/replies, xml ) Need Help??

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

Pardon if "32-bit" is archeology in 2020, it's just that I have some time to debug/develop at that machine -- but can pursue other projects, while postponing this one till later. I.e., question is not urgent/critical, simply puzzling.

Using FreeImage DLL, this C test runs perfectly well:

#include <stdio.h> #include <stdlib.h> #include <FreeImage.h> int main( int argc, char **argv ) { printf("%s\n", FreeImage_GetVersion()); FIBITMAP *im = FreeImage_Load(FreeImage_GetFileType(argv[1], 0), a +rgv[1], 0); printf("%d\n", im); FITAG *tag = FreeImage_CreateTag(); FreeImage_SetTagKey(tag, "Urgency"); FreeImage_SetTagLength(tag, 2); FreeImage_SetTagCount(tag, 2); FreeImage_SetTagType(tag, FIDT_ASCII); FreeImage_SetTagValue(tag, "5"); printf("*\n"); FreeImage_SetMetadata(FIMD_IPTC, im, FreeImage_GetTagKey(tag), tag +); printf("*\n"); FreeImage_DeleteTag(tag); FreeImage_Unload(im); }
>convert wizard: wiz.jpg >convert wizard: wiz.tif >gcc -s -O2 -DWIN32 -fwrapv -fno-strict-aliasing -mms-bitfields -o fit +est.exe fitest.c -lfreeimage >fitest.exe wiz.jpg 3.18.0 2729184 * * >fitest.exe wiz.tif 3.18.0 2728264 * *

However, this Perl script fails:

use strict; use warnings; use FindBin; load( $ARGV[0] ); use Inline C => config => inc => "-I$FindBin::Bin", libs => "-L$FindBin::Bin -lfreeimage"; use Inline C => <<'END_OF_C'; #include <FreeImage.h> void load(char *fname) { // FreeImage_Initialise(FALSE); printf("%s\n", FreeImage_GetVersion()); FIBITMAP *im = FreeImage_Load(FreeImage_GetFileType(fname, 0), fna +me, 0); printf("%d\n", im); FITAG *tag = FreeImage_CreateTag(); FreeImage_SetTagKey(tag, "Urgency"); FreeImage_SetTagLength(tag, 2); FreeImage_SetTagCount(tag, 2); FreeImage_SetTagType(tag, FIDT_ASCII); FreeImage_SetTagValue(tag, "5"); printf("*\n"); FreeImage_SetMetadata(FIMD_IPTC, im, FreeImage_GetTagKey(tag), tag +); printf("*\n"); FreeImage_DeleteTag(tag); FreeImage_Unload(im); // FreeImage_DeInitialise(); } END_OF_C __END__ >perl fitest.pl wiz.jpg 3.18.0 2733096 * >perl fitest.pl wiz.tif 3.18.0

Perl crashes, hence truncated output -- with call to "FreeImage_SetMetadata" for jpg image, and "FreeImage_Load" for tif image. "FreeImage_Initialise" makes no difference (manual says, it's not required to be called), and same compiler options, which Inline uses, work perfect for pure C, above. There is no such issue for 64 bit environment (of course, a dll of appropriate architecture was used in both cases). Why is this happening and can it be (easily) fixed?

Replies are listed 'Best First'.
Re: Errors using DLL from Inline C with 32-bit Perl
by syphilis (Archbishop) on Jan 29, 2020 at 22:56 UTC
    Why is this happening and can it be (easily) fixed?

    The only thing I can think of is that the Inline::C script and the C script are finding different files - either the wiz.* files, or the freeimage library.

    In building the executable, it was unnecessary to provide info regarding the location of the freeimage library.
    Generally that would mean that it's also unnecessary to provide that info to the Inline::C script, so 2 things I would try is to:
    1) remove the "inc =>" spec completely and
    2) change the "lib =>" spec to simply libs => '-lfreeimage'
    That should let the C toolchain find it's own way - just as happened when you built the executable

    I think it has to be something pretty simple.
    IME, when odd stuff like this happens, it's never because Inline::C is doing something it shouldn't - but, of course, there could always be "a first time" ;-)

    Cheers,
    Rob
      the Inline::C script and the C script are finding different files

      Spot on! But problem persists. I'm embarrassed to admit ("what else he forgot to mention?"), that I must have placed FreeImage.dll (and *.lib, and *.h) into appropriate "system" GCC folders, when started experiments a couple weeks ago. However, if I either (1) modify Perl script as you suggest, or (2) delete mentioned files and add "-I. -L." to C command line -- the end results are the same. The compiled exe runs OK, Perl crashes.

      just general debugging advice...

      Thanks, bliako! I've already checked that all functions (including "FreeImage_GetFileType") complete successfully for a TIF, and all up to and including "FreeImage_GetTagKey" for a JPG. And compiler flags for *.c file were taken from *.inl, with Perl related defines omitted. Same result if I copy verbatim from "perl -V:ccflags"

      Anonymous Monk: other info, obtained after click-click in said GUI:

      
      Error signature
      AppName: perl.exe	 AppVer: 5.28.0.1	 ModName: freeimage.dll
      ModVer: 3.18.0.0	 Offset: 00066bf0
      
      

      As I said, the problem is not worth too much effort, please don't waste your time. I can only add, there's PDL::IO::Image which uses Alien::FreeImage, which includes FreeImage source (version 3.017), they work successfully on this 32-bit installation (and, yes, I also tried to clean-delete Alien::FreeImage and its compiled library, no changes).

Re: Errors using DLL from Inline C with 32-bit Perl
by bliako (Monsignor) on Jan 30, 2020 at 12:25 UTC

    Print a pointer using the appropriate formatter:

    printf("%p\n", im);

    It's also a good idea to check that im and tag are returned not-null after the function calls.

    And also call FreeImage_GetFileType(fname, 0) on a separate line to make sure it does return a valid type too.

    Then insert a lot more printf statements to see exactly which function fails.

    just general debugging advice...

    If it's too important then run it through a debugger (not Perl's, I mean gdb or something).

    btw, to add on what syphilis said about making sure the same libraries are loaded (for Inline::C and gcc), make sure that the same compiler flags are used too. There must be a Makefile somewhere created by Inline::C (edit: for your specific script. In linux is in the same dir) which will show you exactly how the C-part of your script is compiled.

    bw, bliako

      make sure that the same compiler flags are used too

      Good point - I now recall being tripped up by different optimization levels in the past.
      However, I think the OP has probably already followed that advice by having built the executable with:
      gcc -s -O2 -DWIN32 -fwrapv -fno-strict-aliasing -mms-bitfields -o fite +st.exe fitest.c -lfreeimage
      Maybe there's some other pertinent option that has been omitted. We can't tell unless we see the output of perl -V:ccflags

      There must be a Makefile somewhere created by Inline::C

      Also a good point - it's usually under the ./_Inline/build directory, but you'll need to configure the Inline::C script with CLEAN_AFTER_BUILD => 0 to prevent the Makefile being automatically deleted when the compilation successfully completes.

      Cheers,
      Rob
Re: Errors using DLL from Inline C with 32-bit Perl
by Anonymous Monk on Jan 29, 2020 at 13:36 UTC
    And exact error message is?

      GUI window "Perl interpreter has encountered a problem and needs to close"

        More info than that

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11112009]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (5)
As of 2024-03-28 08:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found