0

その奇妙な問題を示すサンプルプロジェクトをD7で作成しました。ここにあります: http ://speedy.sh/n9Etr/OpenCV-BugTest.zip

私はそのような手順を持っています:

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

Recを呼び出すと、DLL_CALLでAVを取得しますが、関数に2番目のパラメーターを追加すると次のようになります。

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;

私のすべてのメソッドは、cdeclparamの呼び出し規約でエクスポートされます。

完全な手順は次のとおりです。

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

dll のインポート宣言を確認してください。おそらく、この dll のインターフェイスが変更されていますが、コードにはそれが反映されていません。

于 2012-07-09T18:17:14.163 に答える
1

2.4.1 DLL バージョンで 1.0 関数定義を使用しています。関数の定義が変更されたため、3 年近く古いものになっています。特に、2 つだけでなくcvSaveImage3 つのパラメーターが必要です。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 は、2 つのパラメーターしか渡していないことを認識しないため、3 番目のパラメーターと思われるものから読み取り、整数の配列へのポインターとして解釈します。実際にそこにあるものはおそらくポインターではないため、アクセス違反が発生します。

関数に別のパラメーターを追加するとRec、4 つのパラメーター ( SelfimageSomething、およびResult) が作成され、パラメーターの 1 つが強制的にスタックに置かれます。スタックが少し大きいため、DLL は別の場所から読み取ることになります。その場所にはおそらく null ポインターが保持されているため、DLL は配列要素を読み取ろうとせず、コードは期待どおりに機能します。

于 2012-07-09T14:32:45.987 に答える