2011-06-19 14 views
2

私はOpenCVを使ってトラッキングを行うDLLを開発してきました。 VS 2008を使用してCコンソールプロジェクトで作業しているすべてのものを入手しました(テスト目的)。その後、私は新しいDLLプロジェクトを作り、それをコンパイルしました。私はすべてをセットアップしたので、Threadクラスの単一の関数を呼び出して、単一の関数を呼び出すだけでした。C#のアンマネージDLLが正しく動作しない

次に、GUIなどのためのC#プロジェクトを作成しました。 DLLは正常にロードされます(System.Runtime.InteropServicesを使用すると、メソッドが開始されます(OpenCVによって作成されたキャプチャウィンドウが表示されますが、追跡は行われていません)。 (追跡が行われていました)

管理対象コードの管理対象外のDLLで作業するのは初めてです。間違っていることや、これをどのようにデバッグできますかに関するアイデアはありますか?この問題を解決するために他に何か必要があれば私はそれを提供します、事前に

感謝を

編集:。。

私が使用していませんよDLL上のクラス、私は単一の関数を使用して、スレッドクラスは、C#のSystem.Threadingから来て

私はDLLを使用している方法はこのようなものです。

namespace GUI 
{ 
    static class NativeTracking 
    { 
     [DllImport(@"__Tracking.dll")] 
     public static extern void _Tracking(); 
    } 
} 

のIは、彼の

public GUI() 
{ 
    InitializeComponent(); 
    _tracking = new Thread(_Tracking); 
    _tracking.Start(); 
} 

public _Tracking() 
{ 
    while(True) 
    { 
     NativeTracking.Tracking(); 
    } 
} 

編集などの糸の上に置く:ネイティブコード化された

ネイティブコード、厄介なフォーマットのため申し訳ありません。

ヘッダーファイルDLLIMPORT(P /呼び出し)の問題の

#include <cv.h> 
#include <stdio.h> 
#include <ctype.h> 
#include <windows.h> 
#include <highgui.h> 
#include "..\original\project\myheader.h" 
#include "..\original\project\myheader1.h" 
#include "..\original\project\myheader2.h" 
#include "..\original\project\myheader3.h" 
#include "..\original\project\myheader4.h" 
#ifdef __cplusplus 
extern "C"{ 
#endif 

    _declspec(dllexport) void Tracking(); 

#ifdef __cplusplus 
} 
#endif 

実装

#include "exposed.h" 

void Tracking() 
{ 
int flag = 1, i=0; 
iplImgs imgs; 
trackingTool tools; 
helperTools helperTools; 

CvCapture* capture = 0; 
capture = cvCaptureFromCAM(0); 

cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 320); 
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 240); 
cvSetCaptureProperty(capture, CV_CAP_PROP_FPS, 20.0f); 

imgs.image = 0; 

    cvNamedWindow("Window", 0); 
initHelperTools(&helperTools); 
initTools(&imgs, &tools); 

    for(;;){ 

    int c; 
      IplImage* frame = 0; 

    frame = cvQueryFrame(capture);   
    if(!frame) 
     break; 

    if(!imgs.image){ 
      /* allocate all the buffers */ 
      prepareImages(&imgs, &tools, frame); 
     } 

     cvCopy(frame, imgs.image, 0); 
     cvCvtColor(imgs.image, imgs.grey, CV_BGR2GRAY); 

     if(flag == 1 || conditionB){ 
     someOperations(&imgs, &tools); 
     if (conditionC) 
      flag = 0; 
     } 
    else if(conditionD){ 
     otherOps(&helperTools, imgs.grey); 
     someTrack(&imgs, &tools, &helperTools, drawPoints); 
     someCorrections(&tools); 
     if (condition){ 
      if (!wasReset){ 
       wasReset = 0; 
       continue; 
      } 
      if (validation) 
      someMoreOperations(&tools, corretions); 
     } 
    } 

    bufferHandlingOps(&imgs); 


     c = cvWaitKey(10); 
     if((char)c == 27) 
      break; 
    switch ((char)c){ 
     case 'p': 
      drawPoints ^= 1; 
      break; 
     default: 
      ; 
    } 
    } 

    cvReleaseCapture(&capture); 
    cvDestroyWindow("Window"); 
} 
+3

Cは、クラスを持っていないので、どちらかあなたはドンスレッド・クラスを持っているか、Cを使用していません。 –

+0

DLL上でクラスを使用していません。単一の関数を使用しています。スレッド・クラスはC#の 'System.Threading'から来ています。 – masterLoki

+0

ネイティブの「トラッキング」メソッドを含めるように質問を編集できますか? –

答えて

2

一つは、それがタイプセーフではないです。コンパイル時にチェックする方法がないため、ランタイムのみが動作していることがわかります。

  • このメソッドの署名は正しいものです。
  • この方法のマングリングは正しいです。

多くの例がありますが使用しているライブラリでは非常に一般的ですが、動作するか試してみるか、あなたをブロックしている特定の問題を見つけてください(dllが実行時に実行可能ファイルの同じディレクトリまたはシステムディレクトリにあることを確認してください)。

私の助言は、C++/CLIで適切なラッパーを作成することです。上記の問題はなく、問題が発生した場合にはデバッグするのが賢明です。 Hereは、C#で公開するコールバックの場合に書いたより複雑な例です。

+0

+1のC++/CLIラッパーの提案。これは、この問題を見つけ出す最も簡単な方法のようです。 –

3

ネイティブコードで "__cdecl"というデフォルトのC呼び出し規約を使用していて、P/Invokeの "DLLImport"属性で、 C#は "__stdcall"です。これはおそらくネイティブメソッドを呼び出すたびに実行時例外をスローしています。

また、引数を渡したり結果を期待していないことに気付きましたが、呼び出し規約は関数の装飾方法を示しており、name manglingの問題が発生する可能性があります。 次のことが可能です。 "__declspec(のdllexport)__stdcall無効トラッキング();"

    ことにネイティブのエクスポートを変更
  1. またはあなたのDLLIMPORT属性の "CallingConvention" プロパティを変更:「[DLLIMPORT(@ "__ Tracking.dll")CallingConvention = CallingConvention = CallingConvention.Cdecl]
+0

こんにちは、これを試しました、この '__declspec(dllexport)void __stdcall Tracking();のようにコーディングされましたこの順序を変更した場合、DLLは' DllImport(@ "CamComtrolDll.dll"、CallingConvention = CallingConvention.StdCall) ] '私が' CallingConvention.Cdelc'を使うと、私は 'EntryPointNotFound'例外を持っています。 DLLはブラックボックスであると想定されますが、入力は受け付けられず、システムに直接出力されますが、いくつかの値を返すように変更して管理ソースで処理することができます – masterLoki

+0

@Lokiそうです、それを私が直した。呼び出し規約は、戻り値の型とメソッド名の間に来なければなりません。重要なことは、両方とも同じ呼び出し規則を使用していることです。したがって、私が提案した変更のうちの1つを行うだけで、両方を行うことはできません。また、それはブラックボックスのルーチンであり、呼び出し規約は関数の引数とスタックのバランスを取るために使用されていますが、名前のマングリングが発生する可能性があるため、これを述べました。私はまたあなたと全く同じように設定されたサンプルプロジェクトを作成します(明らかにopencvを除いて) –

+0

と私は何の問題もなく、すべてが期待どおりに動作しています。エラーの原因を絞り込むために新しいスレッドを作成せずに実行しようとしましたか? –

関連する問題