John
John

Reputation: 1913

Strange AV during DLL call

I have created a sample project in D7 demonstrating that strange issue. It is here: http://speedy.sh/n9Etr/OpenCV-BugTest.zip

I have a procedure which looks like that:

function Rec (image: PIplImage): String;
begin
  DLL_CALL;
end;

When I call Rec, I get AV on DLL_CALL, but ... If I Add Second parameter to the function:

function Rec (image: PIplImage; Something: String): String;
begin
  DLL_CALL;
end;

Then DLL_CALL succeed.

Variable: 'Something' is irrelevant and is not taken anywhere ...

Really, I don't know what is happening ...

EDIT:

I use cvSaveImage of openCV library.

function cvSaveImage(const filename: PAnsiChar; const image: pointer): integer; 
    cdecl; external CV_HIGH_GUI_DLL;

All my methods are exported with cdecl param's call convention.

The complete procedure is:

function TCVR.Rec(image: PIplImage): String;
const
  THRESH = 50;
var
  imgDisorted: PIplImage;
  Storage: PCvMemStorage;
  Squares: PCvSeq;

begin
  imgDisorted := nil;
  result := '';

  Storage := cvCreateMemStorage(0);

  cvSetImageROI(image, cvRect(0, 0, image^.width and -2, image^.height and -2));
  PyrDownUp(image);
  cvSetImageROI(image, cvRect(0, 0, image^.width and -2, image^.height and -2));

  imgDisorted := cvCreateImage(cvSize(image^.width and -2, image^.height and -2), 8, 1);
  cvSaveImage('c:\test.jpg', image); <--- AV here only when I have 1 parameter in my Rec.
end;

Upvotes: 0

Views: 332

Answers (2)

Torbins
Torbins

Reputation: 2216

Check import declarations of your dll. Probably interface of this dll has changed, but your code doesn't reflect that.

Upvotes: 1

Rob Kennedy
Rob Kennedy

Reputation: 163277

You're using 1.0 function definitions with a 2.4.1 DLL version. The function definitions changed, so you're nearly three years out of date. In particular, cvSaveImage expects three parameters, not just two. An excerpt from the 2.0 release:

CVAPI(int) cvSaveImage( const char* filename, const CvArr* image,
                        const int* params CV_DEFAULT(0) );

Update your DLL import unit to match the DLL you're using (or switch to an older version of the library). I'd translate that function to Delphi like this:

function cvSaveImage(filename: PAnsiChar; image: PCvArr; params: PInteger = nil); cdecl;

Here's why you get the particular failure you saw:

The DLL doesn't know that you're only passing two parameters, so it reads from what it believes to be the third parameter and interprets it as a pointer to an array of integers. Whatever's really there probably isn't a pointer at all, and so you get an access violation.

Adding another parameter to your Rec function causes it to have four parameters (Self, image, Something, and Result), which forces one of the parameters onto the stack. Since the stack is a little bigger, the DLL ends up reading from a different location. That location probably holds a null pointer, so the DLL doesn't try to read any array elements, and so the code works as expected.

Upvotes: 1

Related Questions