Thread overview
Problem calling extern(C) function
Dec 15, 2014
AuoroP
Dec 15, 2014
Adam D. Ruppe
Dec 16, 2014
AuoroP
December 15, 2014
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



December 15, 2014
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.
December 16, 2014
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