Смешанный код C ++ / CLI с Беркли DB - PullRequest
1 голос
/ 19 апреля 2011

Я хочу использовать Berkeley DB в C ++ / CLI с режимом /clr. Я написал этот код:

Edit:

// 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 !");

Ответы [ 2 ]

2 голосов
/ 21 апреля 2011

Я вижу две проблемы с вашим приложением:

1) Два вызова Marshal :: FreeHGlobal выполняются перед использованием содержимого буферов.Вы не должны освобождать 'A' до окончания операции put, и вы не должны освобождать 'A' до тех пор, пока не завершены операции put и get.

2) Скорее всего, вы храните указатели в DB Беркли.чем сами струны.Это связано с вызовами конструктора Dbt.Ваше приложение: Dbt key1 (& a, 100);Должно быть: Dbt key1 (a, 100);

Аналогично для метода getKey.set_data - он должен использовать указатель, а не ссылку на указатель.

Как только я сделал вышеПосле внесения изменений в ваше приложение оно запустилось, как и ожидалось.

С уважением, Алекс Горрод, Oracle Berkeley DB

1 голос
/ 19 апреля 2011

Вы используете Marshal :: StringToHGlobalUni (), преобразованная строка - это wchar_t *, а не char *. Широкая строка с кодовыми точками Unicode, закодированными в utf16. Чтобы получить символ *, вам нужно StringToHGlobalAnsi ().

Считайте, что это преобразование с потерями, движки dbase поддерживают Unicode уже более десяти лет. Другая серьезная проблема заключается в том, что вы не освобождаете память, выделенную для этой строки, требуется вызов Marshal :: FreeHGlobal () в блоке finally. Вы также должны технически использовать GlobalLock () для преобразования возвращенного HGLOBAL в указатель, рассмотрим Marshal :: StringToCoTaskMemXxx.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...