0

我在 D7 中创建了一个示例项目来演示这个奇怪的问题。它在这里: http ://speedy.sh/n9Etr/OpenCV-BugTest.zip

我有一个看起来像这样的程序:

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

当我调用 Rec 时,我在 DLL_CALL 上得到了 AV,但是......如果我向函数添加第二个参数:

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

然后 DLL_CALL 成功。

变量:“某事”是无关紧要的,不会被带到任何地方......

真的,我不知道发生了什么……

编辑:

我使用 openCV 库的 cvSaveImage。

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

我所有的方法都使用 cdecl 参数的调用约定导出。

完整的程序是:

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;
4

2 回答 2

1

您将 1.0 函数定义与 2.4.1 DLL 版本一起使用。函数定义发生了变化,所以你已经过时了将近三年。特别是,cvSaveImage需要三个参数,而不仅仅是两个。2.0 版本的摘录:

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

更新您的 DLL 导入单元以匹配您正在使用的 DLL(或切换到旧版本的库)。我会像这样将该函数翻译为Delphi:

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

这就是为什么你会看到你看到的特定失败:

DLL 不知道您只传递了两个参数,因此它从它认为是第三个参数的内容中读取数据,并将其解释为指向整数数组的指针。真正存在的东西可能根本就没有指针,因此您会遇到访问冲突。

向函数添加另一个参数Rec会使其具有四个参数(SelfimageSomethingResult),这会将其中一个参数强制到堆栈中。由于堆栈稍大一些,因此 DLL 最终会从不同的位置读取。该位置可能包含一个空指针,因此 DLL 不会尝试读取任何数组元素,因此代码可以按预期工作。

于 2012-07-09T14:32:45.987 回答
1

检查您的 dll 的导入声明。可能此 dll 的接口已更改,但您的代码并未反映这一点。

于 2012-07-09T18:17:14.163 回答