Передача данных из Vc++ Dll в Dlphi App

Тема в разделе "MS Visual C++", создана пользователем Kosoglaz, 1 фев 2008.

  1. Kosoglaz

    Kosoglaz Гость

    Здравствуйте, программисты!
    Помогите, пожалйста, решить проблему передачи данных между приложением Delphi 2007 и DLL MS Visual C++ 6

    Идея такая, что Delphi App делает запрос DLLке, а та возвращает данные.
    Вот код C++

    #define EXPORTCALLstd extern "C" __declspec(dllexport) __stdcall
    typedef struct {
    int nLevel;
    const char* name;
    double fVal;
    const char* szVal;
    }ITEMDATA;

    const char* Names[10] = {"January","February","March","April","May","June","July","August","September","October"};
    double fVals[10] = {1.99,2.88,3.77,4.66,5.55,6.44,7.33,8.22,9.11,10.111};
    const char* szVals[10] = {"A","B","C","D","E","F","G","H","I","J"};
    ...

    EXPORTCALLstd int GetDataCount()
    {
    return 10;
    }

    EXPORTCALLstd int SendItemData(int nIndex, PITEMDATA pItemData)
    {
    ITEMDATA ItData;

    if(nIndex > 9)
    nIndex = 9;

    ItData.fVal = fVals[nIndex];
    ItData.name = Names[nIndex];
    ItData.nLevel = nIndex;
    ItData.szVal = szVals[nIndex];

    //тут вываливается 0xC0000005
    (*ItemData).fVal = fVals[nIndex];
    (*ItemData).name = (const char*)Names[nIndex];


    return 0;
    }
    /* вариант со структурой
    EXPORTCALLstd int SendItemData(int nIndex, int* nLevel, char* name, double* fVal, char* szVal)
    {
    if(nIndex > 9)
    nIndex = 9;

    *nLevel = nIndex;
    *fVal = fVals[nIndex];

    /*
    mx = strlen(Names[nIndex]);
    szVal = (char*)malloc(mx);
    for(i=0; i < mx; i++)
    {
    *szVal = Names[nIndex];
    szVal++;
    }
    */
    return 1;
    }
    */
    EXPORTCALLstd int SendItemData(int nIndex, int* nLevel, char* name, double* fVal, char* szVal)
    {
    int i,mx;

    if(nIndex > 9)
    nIndex = 9;

    *nLevel = nIndex;
    *fVal = fVals[nIndex];

    mx = strlen(Names[nIndex]);
    for(i=0; i < mx; i++)
    {
    *name = Names[nIndex];
    name++;
    }
    name = '\0';

    mx = strlen(szVals[nIndex]);
    for(i=0; i < mx; i++)
    {
    *szVal = szVals[nIndex];
    szVal++;
    }
    szVal = '\0';

    return 1;
    }


    Вариант с параметрами работает, но строковые значения криво возвращаются. Дежучник в Си показывает после вызова из Дельфи с nIndex = 0, что name = 'January', а в уже Дельфи после вызова name = ''anuary'#0#0#0#0#0#0#0#0#0'е'#8'яяі'#2#0#0#1#0#0#0#$E#0#0#0' Ѓ¦'#0'шф'#$12#0'fгУwе'#8'яяf'#$B#$1C#0#$E#0#0#0#0#0#0#0#0#0#0#0#1#0#0#0'Lц'#$12#0'|'#$1E'D'

    Вот код Delphi

    type
    PInteger = ^Integer;
    PDouble = ^Double;

    PTITEMDATA = ^TITEMDATA;
    TITEMDATA = record
    nLevel:integer;
    szName:ShortString;
    fVal:double;
    szVal:ShortString;
    end;

    TformMain = class(TForm)
    btRequestData: TButton;
    sgrData: TStringGrid;
    btChangeData: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btRequestDataClick(Sender: TObject);
    private
    { Private declarations }
    public
    { Public declarations }

    CppFnGetDataitemsCnt: function: integer; stdcall;
    //CppFnGetItemData: function(nIndex:integer; ItemData:TITEMDATA):integer;
    CppFnGetItemData: function(nIndex:integer; nLevel:pInteger; Name:pChar; fVal:pDouble; szVal:pChar):integer; stdcall;
    end;

    procedure TformMain.FormCreate(Sender: TObject);
    var
    HLib:THandle;
    begin
    formMain := self;

    //загрузь
    HLib := LoadLibrary('..\CDT_CppDLL\Debug\CDT_CppDLL.dll');
    if HLib < 32 then
    ShowMessage('Lib didn`t load')
    else
    begin
    CppFnGetDataItemsCnt := GetProcAddress(HLib,'_GetDataCount@0');
    if(not Assigned(CppFnGetDataitemsCnt)) then
    ShowMessage('Didn`t find GetDataCount func in lib ');
    CppFnGetItemData := GetProcAddress(HLib,'_SendItemData@20');
    if(not Assigned(CppFnGetItemData)) then
    ShowMessage('Didn`t find SendItemData func in lib ');
    end;
    end;

    procedure TformMain.btRequestDataClick(Sender: TObject);
    var
    i: integer;
    nDataCnt:integer;
    nLevel:integer;
    Name,szVal:ShortString;
    fVal:double;
    ItemData:TITEMDATA;
    begin
    //это работает отлично
    nDataCnt := CppFnGetDataItemsCnt;
    for i:=0 to (nDataCnt - 1) do
    begin

    nLevel := 333;
    Name := '_123_';
    fVal := 25.52;
    szVal := '-321-';
    //грамотно изменяет числовые значения, но строковые возвращает краказяблами
    CppFnGetItemData(i,@nLevel,@Name,@fVal,@szVal);

    {
    ItemData.nLevel := 999;
    ItemData.szName := 'start name';
    ItemData.fVal := 9.99;
    ItemData.szVal := 'start val';
    CppFnGetItemData(i,ItemData);
    }
    end;
    end;


    Такие вот дела. Не пойму, в чёи проблемы. А главное, не знаю уже отлаженного решения передачи данных, в т.ч. строковых из СиПП ДЛЛ в Дельфи приложение.
    Подскажите решение, пожалуйста. А ещё лучше, если объясните суть проблемы, чтобы я мог сам понять как это всё делается и почему не делается.
    Спасибо!
     
  2. grigsoft

    grigsoft Well-Known Member

    Регистрация:
    15 ноя 2005
    Сообщения:
    735
    Симпатии:
    0
    Ну так char* в C++ это указатель на кусок памяти, где с первого байта находятся символы строки. А что такое ShortString? Со структурами еще хуже - там начинается разное выравнивание и прочие радости. Для надежности я бы передавал в длл указатель на память, выделенную через GlocaAlloc, туда складываются результаты, приложение их извлекает.
     
  3. Kosoglaz

    Kosoglaz Гость

    Спасибо за подсказку!
    Действительно, представление ShortString в Delphi такое: 0ой символ - длина строки, остальные - содержимое без нулевого на конце.
    Просто поменял в Си коде:
    mx = strlen(Names[nIndex]);
    for(i=0; i < btStrLen; i++)
    {
    *name= Names[nIndex];
    name++;
    }
    name = '\0';

    на

    btStrLen = (char)strlen(Names[nIndex]);
    *name = btStrLen;
    for(i=0; i < btStrLen; i++)
    {
    *(++name) = Names[nIndex];
    }

    И всё работает!
     
Загрузка...
Похожие Темы - Передача данных из
  1. sergg
    Ответов:
    7
    Просмотров:
    4.471
  2. Vadik(R)
    Ответов:
    0
    Просмотров:
    1.764
  3. Corexis
    Ответов:
    0
    Просмотров:
    71
  4. Shouldercannon
    Ответов:
    0
    Просмотров:
    488
  5. Shouldercannon
    Ответов:
    0
    Просмотров:
    388

Поделиться этой страницей