Reputation: 1913
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 ...
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
Reputation: 2216
Check import declarations of your dll. Probably interface of this dll has changed, but your code doesn't reflect that.
Upvotes: 1
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