2011-04-19 74 views
1

我正在試圖在C++/CLI中使用帶有/clr模式的Berkeley DB。我寫了這個代碼:與Berkeley DB混合的C++/CLI代碼

編輯:

// DB_test1.cpp : main project file. 

#include "stdafx.h" 
#pragma comment(lib,"libdb51") 
using namespace System; 
using namespace System::Runtime::InteropServices; 

int main(array<System::String ^> ^args) 
{ 
    Db SigDb(0,0); 
    unsigned int oFlags= DB_CREATE; 
    SigDb.open(NULL,"SigDb.db",0,DB_BTREE,oFlags,0); 
    String^ HexSig="D8B1048900ABFF8B"; 
    wchar_t* a=(wchar_t*)Marshal::StringToHGlobalUni(HexSig).ToPointer() ; 
    wchar_t* A=(wchar_t*)Marshal::StringToHGlobalUni(HexSig).ToPointer();; 

    Dbt key1(&a,100); 
    Dbt data1(&A,100); 

    Marshal::FreeHGlobal(IntPtr(A)); 
    int ret= SigDb.put(NULL,&key1,&data1, DB_NOOVERWRITE); 
    if(ret==DB_KEYEXIST){ 
     Console::WriteLine("You are trying to insert an exist key!"); 
    } 


    wchar_t DDData[200]; 
    Dbt getKey, getData; 
    getKey.set_data(&a); 

    getKey.set_size(100); 
    getData.set_data(DDData); 
    getData.set_ulen(200); 
    getData.set_flags(DB_DBT_USERMEM); 
    Marshal::FreeHGlobal(IntPtr(a)); 
    if(SigDb.get(NULL,&getKey,&getData,0)==DB_NOTFOUND) 
     Console::WriteLine("Not Found !"); 
    else 
     Console::WriteLine(" {0}",Marshal::PtrToStringUni((IntPtr)DDData)); 


    return 0; 
} 

的代碼編譯成功,但它顯示了錯誤的輸出。我只是traying存儲String^ HexSig="D8B1048900ABFF8B";SigDb.db,然後直接讀取相同的字符串,並打印它!結果不像預期的那樣出現D8B1048900ABFF8B,但它顯示爲隨機字符串。有任何想法嗎?

編輯後: 這個代碼段始終執行Console::WriteLine("Not Found !");

回答

2

我可以看到兩個問題與您的應用程序:

1)兩個呼叫到元帥:FreeHGlobal使用緩衝區的內容之前進行。在放置操作之前,您不應該釋放'A',並且在放置和取得操作之後,您不應該釋放'a'。

2)您將指針存儲在Berkeley DB中,而不是字符串本身。這是由於Dbt構造函數調用。您申請的是: Dbt key1(& a,100); 它應該是: Dbt key1(a,100);

同樣,對於getKey.set_data方法 - 它應該使用指針,而不是對指針的引用。

一旦我對應用程序進行了上述更改,它就按預期運行。

問候, 亞歷Gorrod Oracle Berkeley數據庫

+0

非常感謝Alex!這個問題已經通過你的筆記解決了! – Aan 2011-04-22 16:45:12

1

您使用元帥:StringToHGlobalUni(),轉換後的字符串是wchar_t的*,而不是一個char *。 Unicode編碼點編碼爲utf16的寬字符串。要獲得char *,你需要StringToHGlobalAnsi()。

不要認爲這是一個有損轉換,dbase引擎已啓用Unicode十多年了。另一個嚴重的問題是,你不釋放分配給這個字符串的內存,在finally塊中調用Marshal :: FreeHGlobal()是必需的。你還應該從技術上使用GlobalLock()將返回的HGLOBAL轉換爲指針,考慮Marshal :: StringToCoTaskMemXxx。

+0

@Hans我做了你的建議,我無法在數據庫中找到字符串一些修改,它總是顯示始終執行的代碼,這部分'控制檯:的WriteLine (「Not Found!」);' – Aan 2011-04-19 13:34:15

+0

我可以幫助您找回它的機率不大。如果你沒有從put()中得到錯誤返回,那麼就寫了一些東西。請注意,您的錯誤檢查代碼不正確,您只能捕獲DB_KEYEXIST。 – 2011-04-19 17:01:47

+0

我確定類似'String^HexSig'的內容被寫入數據庫(或確切的String^HexSig內容)。我覺得問題在於閱讀參數,但我無法確定它的確切位置! – Aan 2011-04-19 17:26:40