1

モードを使用して C++/CLI で Berkeley DB を使用しようとしてい/clrます。私はこのコードを書きました:

編集:

// 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;
}

コードは正常にコンパイルされますが、間違った出力が表示されます。保存String^ HexSig="D8B1048900ABFF8B"; してSigDb.dbから、同じ文字列を直接読み取って印刷しようとしています!. 結果は期待どおりに表示されませんがD8B1048900ABFF8B、ランダムな文字列として表示されます。何か案は?

編集後: このコード セグメントは常に実行されます。Console::WriteLine("Not Found !");

4

2 に答える 2

2

あなたのアプリケーションには 2 つの問題があります。

1) Marshal::FreeHGlobal への 2 つの呼び出しは、バッファの内容が使用される前に行われます。put 操作の後まで「A」を解放しないでください。また、put 操作と get 操作の両方の後まで「a」を解放しないでください。

2) 文字列自体ではなく、ポインターを Berkeley DB に格納しています。これは、Dbt コンストラクター呼び出しによるものです。あなたのアプリケーションは次のとおりです。 Dbt key1(&a,100); 次のようになります: Dbt key1(a, 100);

getKey.set_data メソッドについても同様です。ポインターへの参照ではなく、ポインターを使用する必要があります。

アプリケーションに上記の変更を加えると、期待どおりに動作しました。

よろしく、 アレックス・ゴロッド Oracle Berkeley DB

于 2011-04-21T00:23:23.017 に答える
1

Marshal::StringToHGlobalUni() を使用すると、変換された文字列は char* ではなく wchar_t* になります。utf16 でエンコードされた Unicode コードポイントを持つワイド文字列。char* を取得するには、StringToHGlobalAnsi() が必要です。

これは損失の多い変換であると考えてください。dbase エンジンは 10 年以上も前から Unicode に対応しています。もう 1 つの深刻な問題は、この文字列に割り当てられたメモリを解放しないことです。finally ブロックで Marshal::FreeHGlobal() を呼び出す必要があります。また、返された HGLOBAL をポインタに変換するために GlobalLock() を技術的に使用する必要があります。Marshal::StringToCoTaskMemXxx を検討してください。

于 2011-04-19T12:50:59.577 に答える