www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Problem calling extern(C) function

reply AuoroP via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
I'm pretty sure my problem isn't my code but how I've built the
lib. The problem is I'm calling external C code and I am getting
valid data out of it but /some/ of my arguments to it is
corrupted.

A common thread in this newsgroup seems to be people calling
Extern(Windows). I don't that is me because I call with
extern(C) my .lst names are not mangled that way:
_tjDecompressHeader2, _tjGetErrorStr, _tjInitDecompress.

Even if you can't help, Thanks for reading this far!

This message is kinda long so here's a TOC

The code
The output
DLL code:
You WANT to be in this mess?


-------=-------=---------------=---------------=-------=-------
The code:

extern(C) tjhandle tjInitDecompress();
extern(C) int tjDecompressHeader2
(
    tjhandle handle, 
    void* jpegBuf,
    ulong jpegSize,
    int* width,
    int* height,
    int* jpegSubsamp
);
extern(C) char* tjGetErrorStr();

import std.conv: to;    
import std.file: exists, read;
import std.stdio: writeln;

tjhandle dHandle = tjInitDecompress();
writeln("dHandle: ", dHandle);
int width, height, subsamp;
void[] buffer = read("testimg.jpg");

writeln("buffer.ptr: ", buffer.ptr);
writeln("buffer.length: ", buffer.length);
writeln("&width: ", &width);
writeln("&height: ", &height);
writeln("&subsamp: ", &subsamp);
if 
( 
    0 > 
    tjDecompressHeader2
    ( 
        dHandle, 
        buffer.ptr, 
        buffer.length,
        &width,
        &height,
        &subsamp
    )
)
{
    writeln(  to!string( tjGetErrorStr() )  );
    writeln("testimg.jpg gets me ", buffer.length, "bytes.");
    write("width: ", width);
    write(" height: ", height);
    writeln("subsamp: ", subsamp);
}


-------=-------=---------------=---------------=-------=-------
The output:

dHandle: 5E09F0
buffer.ptr: 2340000
buffer.length: 5764
&width: 18FDC4
&height: 18FDC8
&subsamp: 18FDCC
tjDecompressHeader2(): Invalid argument
testimg.jpg gets me 5764bytes.
width: 0 height: 0subsamp: 0


-------=-------=---------------=---------------=-------=-------
DLL code:

If you wanted to look in the DLL code, it is online here:
https://github.com/LibVNC/libvncserver/blob/master/common/turbojpeg.c

DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle,
unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
int *jpegSubsamp)
{
    int retval=0;
    getinstance(handle);
    if((this->init&DECOMPRESS)==0)
        _throw("tjDecompressHeader2(): Instance has not been initialized for
decompression");
    if
    (
        jpegBuf==NULL || 
        jpegSize<=0 || 
        width==NULL || 
        height==NULL|| 
        jpegSubsamp==NULL
    )
        _throw("tjDecompressHeader2(): Invalid argument");
    // .
    // .
    // .
}


-------=-------=---------------=---------------=-------=-------
You WANT to be in this mess?

If you want to play with this problem yourself then I'll help you recreate it.

I'm using 1.3.1 libjpeg-turbo which can be found here:
http://sourceforge.net/projects/libjpeg-turbo/files/1.3.1/libjpeg-turbo-1.3.1-vc.exe/download

I've gotten working .lib files out of the folders lib and bin


Getting a .lib from the DLL in bin is much more straightforward:

IMPLIB /s libTurboJPEG.lib turbojpeg.dll
LIB -l libTurboJPEG.lib

Getting a .lib from lib is tricky but the following gets you turbojpeg.omf.lib:

COFFIMPLIB turbojpeg.lib turbojpeg.omf.lib
ECHO LIB -l turbojpeg.omf.lib


I've tried to use both .lib files and their behavior is the same.

Next up is trying the GCC version with the same recipes:
http://sourceforge.net/projects/libjpeg-turbo/files/1.3.1/libjpeg-turbo-1.3.1-gcc.exe/download

The behavior is unchanged.

____________________________________________________________
FREE 3D EARTH SCREENSAVER - Watch the Earth right on your desktop!
Check it out at http://www.inbox.com/earth
Dec 15 2014
next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Monday, 15 December 2014 at 17:48:32 UTC, AuoroP via 
Digitalmars-d-learn wrote:
     ulong jpegSize,
Without looking too closely, this sets off an alarm to me: C's long and D's long are not really compatible because C's long has variable size and D's long is 64 bit. I'd say try "import core.stdc.config;" and replace all instances of ulong with c_ulong and all instances of long with c_long when interfacing with C.
 DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle,
 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int 
 *height,
yeah the D long is 32 bits longer than the C function expects, so every argument after it is offset by that amount.
Dec 15 2014
prev sibling parent AuoroP via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
Thank you!!!

All I have to do is 


 -----Original Message-----
 From: digitalmars-d-learn puremagic.com
 Sent: Mon, 15 Dec 2014 17:54:51 +0000
 To: digitalmars-d-learn puremagic.com
 Subject: Re: Problem calling extern(C) function
 
 On Monday, 15 December 2014 at 17:48:32 UTC, AuoroP via
 Digitalmars-d-learn wrote:
     ulong jpegSize,
Without looking too closely, this sets off an alarm to me: C's long and D's long are not really compatible because C's long has variable size and D's long is 64 bit. I'd say try "import core.stdc.config;" and replace all instances of ulong with c_ulong and all instances of long with c_long when interfacing with C.
Adam D. Ruppe, I have two words for you: thank you!!! I just changed jpegSize from ulong to uint and it worked! I think I had given up so I really cannot express the joy you've given me so thank you again! ____________________________________________________________ Can't remember your password? Do you need a strong and secure password? Use Password manager! It stores your passwords & protects your account. Check it out at http://mysecurelogon.com/manager
Dec 15 2014