2012-07-17 109 views
1

我一直在徘徊在這個問題的靜態與非靜態,回調函數,函數指針等...我的目標是訪問一個結構的數據範圍之外我的回調界面。我正在嘗試在我的課程TextDetect中執行此操作。當我提出這個問題時,我認爲自己正處於正軌:Avoiding a static member function in c++ when using a callback interface from C 但是,我仍然無法訪問數據而不會丟失我最感興趣的數據範圍。在運行時,我得到「訪問違規讀取位置......」我會在下面指出它失敗的地方。 (注意:vtrInitialize是第三方api代碼的一部分int vtrInitialize(const char * inifile,vtrCallback cb,void * calldata);):訪問變量超出回調範圍C++

class TextDetect { 
    const char * inifile; 
    vtrImage *vtrimage; 
    int framecount; 
public: 
    TextDetect(); 
    ~TextDetect(); 
    void vtrCB(vtrTextTrack *track); 
    static void vtrCB_thunk(vtrTextTrack *track, void *calldata); 
    int vtrTest(cv::Mat); 
    bool DrawBox(cv::Mat&); 
    vtrTextTrack *texttrack; 
}; 

TextDetect::TextDetect() : inifile("vtr.ini") 
{ 
     if (vtrInitialize(inifile, vtrCB_thunk, static_cast<void *>(this)) == -1) 
     std::cout << "Error: Failure to initialize" << std::endl; 
     vtrimage = new vtrImage; 
    } 


    int TextDetect::vtrTest(cv::Mat imagetest) 
    { 
    /*store image data in an image structure*/ 
    } 

    void TextDetect::vtrCB(vtrTextTrack *track) 
    { 
    /*send data to command line from callback */     

我試圖複製數據,我需要通過各種方式並沒有什麼作品(這個代碼是從上面的延續):

 //texttrack = track; 
    //texttrack = new vtrTextTrack (*track); 
    memcpy(texttrack,track,sizeof(*track)); 
    //vtrTextTrackFree(track); 

    } 
    void TextDetect::vtrCB_thunk(vtrTextTrack *track, void *calldata) 
    { 
     static_cast<TextDetect *>(calldata)->vtrCB(track); 
    } 

這是成員函數是我想要的數據是用過的。這一點,TextTrack是公共成員,所以我可能需要我的類之外還有(此代碼是從上面的延續):

bool TextDetect::DrawBox(cv::Mat& tobeboxed) 
    { 

我在運行時獲得訪問衝突錯誤在這裏這行代碼(這個代碼從以上延續):

if (texttrack->best->ocrconf > 90) 
    { 
     /*do some more stuff*/ 
    } 
    } 
+5

老實說,是真的那麼多的代碼來描述你的問題? – 2012-07-17 19:49:35

+0

你寫在表單上的問題很難快速理解;也許簡化它會促使更多人回答。 – 2012-07-17 19:51:42

+1

嗯,你的'memcpy'確實是一個錯誤:它不可能複製'track'的所有內容,因爲你顯然在'track'中有指針,它將被複制,但不是它們指向的內容。我可以很容易想象,在回調之外,「track」數據不存在。 – fork0 2012-07-17 19:57:51

回答

1

希望我正確理解這一點。

在我看來,問題是試圖不正確地複製這些vtrTextTrack結構。 這個:

//texttrack = track; 

只是複製指針。如果結構的所有者(可能是回調函數的調用者)破壞/刪除了vtrTextTrack,那麼您將持有一個無效指針。

這一個:

memcpy(texttrack,track,sizeof(*track)); 

將複製vtrTextTrack的所有成員,但不會複製什麼東西被指向它的成員指針(例如texttrack->best)。再說一遍,如果所有者破壞/刪除軌道,那麼您將繼續使用無效指針。

而且由於

//texttrack = new vtrTextTrack (*track); 

沒有工作,我猜vtrTextTrack不提供拷貝構造函數。

至於解決方法,首先檢查您的第三方庫是否提供了複製這些結構的函數。如果情況並非如此(這是否可以通過設計?),那麼您可能必須自己實施一個。這可能很難,因爲可能有各種你不知道的內部信息。如果你不需要整個vtrTextTrack,我會說定義另一個結構並只存儲你需要的信息。東西沿線

SomeType* bestCopier(SomeType* src) 
{ 
    SomeType* temp; 
    /* copy over struct */ 
    return temp; 
} 

Foo* fooCopier(Foo* src) 
{ 
    /*...*/ 
} 

struct myTextTrack 
{ 
public: 
    myTextTrack(vtrTextTrack* src) 
    { 
     //copy over stuff 
     m_best = bestCopier(src->best); 
     m_foo = fooCopier(src->foo); 
    } 

private: 
    /* the members you care about*/ 
    SomeType* m_best; 
    Foo * m_foo; 
} 
+0

謝謝你的回答。讓我玩你的想法並報告回來。 – user1530101 2012-07-18 13:22:28

+0

當我玩這個問題來了。 1)最好的API vtrTextTrack是一個指針。這是否意味着上例中的SomeType應該是SomeType * best?這會改變你的例子中的任何東西嗎? 2)SomeType實際上是另一個結構(在C而不是C++中)。這是否意味着我必須爲上面示例中聲明的結構創建自己的拷貝構造函數? SomeType也有指針。 – user1530101 2012-07-18 13:53:51

+0

你說得對,我的代碼不太對。我做了一些改變,而這只是一種你可以接近的方法。由於這些都是C結構,並且沒有拷貝構造函數,因此您可能只需爲每個部分編寫一個拷貝函數。這不會很有趣,這是肯定的。你需要保留實際的vtrTextTrack結構,還是隻保留其中的某些信息?因爲後者會更容易。此外,值得回顧一下,並考慮是否有另一種方式來完成與第三方庫模型更好相同的事情。 – Ari 2012-07-18 15:57:15