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;
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,
cvSaveImageexpects three parameters, not just two. An excerpt from the 2.0 release: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:
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
Recfunction causes it to have four parameters (Self,image,Something, andResult), 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.