Нюансы памяти на стыке Vc++ Dll и Delphi App

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

  1. Kosoglaz

    Kosoglaz Гость

    Здравствуйте!
    Есть приложение из dll (на Visual C++ 6.0 SP5) и exe (на Delphi 2007).
    Они обмениваются данными через функции:

    1. Запрос от exe к dll на получение данных
    dll:
    Код (Text):
    #define EXPORTCALLstd extern "C" int __declspec(dllexport) __stdcall;
    EXPORTCALLstd SendData(bool bCalculate, TfuncDelphiDataReciever *func)
    exe:
    Код (Text):
    CppFnGetData(true,@DataReciever);
    2. Отправка данных из dll в exe
    dll: код C++
    Код (Text):
    int SendItemData(ULONG ulAddr, ULONG ulParent, char* szType, char* szName, char* szDimension, double *Values, UINT uiValuesCnt, char* ValuesStr, char* szDescription, char* szInnerName)
    {
    ...
    /*ulAddr - адрес объекта в dll.
    Получается так:
    внутри объекта
    ulAddr = (ULONG)this;
    SendItemData(ulAddr,...);
    */
    (*DelphiDataReciever)(ulAddr,ulParent,szName,szType,szDimension,Values,uiValuesC
    nt,ValuesStr,szDescription,szInnerName);
    ...
    }
    exe:
    Код (Text):
    function DataReciever(ulAddr:longword; ulParent:longword; pszName:PChar; pszType:PChar; pszDimension:PChar; Values:PDouble; uiValuesCnt:word; pszValuesStr:PChar; pszDescription:PChar; pszInnerName:PChar):integer;stdcall;
    3. Изменение данных в dll. Вызывает exe
    exe:
    Код (Text):
    CppFnSetItemData: function(ulDataAddr:Cardinal; pszType:PChar; Values:PDouble; uiValuesCnt:longword; pszValuesStr:PChar):integer; stdcall;
    dll: код C++
    Код (Text):
    EXPORTCALLstd ChangeItemData(ULONG uiDataAddr, char* szType, double* Values, UINT uiValuesCnt, char* szValuesStr)
    {
    ...
    ivObject* obj = (ivObject*)uiDataAddr;
    ...
    if(strcmp(szType,cc_ItemType_Real) == 0)
    {
    *((ivReal*)obj) = Values[0];
    }
    ...
    }
    Данные из dll в exe передаются отлично, многократно, точно и без запинок.
    Но!
    Если поменять данные, т.е. вызвать из exe ф-ию dll-ки ChangeItemData, то:
    E1) объект по адресу находится именно тот. Проверял много раз на дебагере, все адреса, все значения полей объекта, всё верно.
    E2) значение ivReal::value (ivReal & operator = ( double val ) { value = val ; return *this; }; сам value в protected зоне) меняется, с того какое действительно есть, на какое указано

    E3) Суть проблемы.
    После изменения данных при повторной отсылке из dll в exe (см п. 1, 2) в dll коде появляются откровенные глюки.
    Например прикод C++

    Код (Text):
    void ivReal::SaveStructureData(ULONG ulParent)
    {
    #ifdef _DLL32
    //try
    //{
    CString name = "";

    if (!IsHide())
    {
    ULONG ulAddr = (ULONG)this;
    //ULONG ulAddr = (ULONG)(&value);
    tmpReal *tmp = GetTmpReal();
    ASSERT( tmp != NULL );

    //ПАДАЕТ ТУТ
    CString Dimension;
    if( tmp->dim )
    tmp->dim->GetNameElem(Dimension, eRus);

    CString ValueStr;
    при вызове GetNameElemкод C++

    Код (Text):
    void Dimension::GetNameElem( CString &nm , eLang el )
    {
    POSITION ps = dimS.FindIndex( indElem );
    if( ps )
    dimS.GetAt( ps )->GetName( nm , el ) ;
    }
    падение происходит внутри CObList::FindIndex, родной MFC-ой функции. (CTypedPtrList< CObList , ElemDimension *> dimS);
    "Access violation at address 756C6156. Read of address 756C6156".
    Причём не на первом считываемом элементе типа ivReal, а на 30ом.

    Помогите, пожалуйста, найти, где тут собака порылась!
    И что тут сделать-то?!!
    (CTypedPtrList с указателями на объекты вместо прямого обращения к объектам по указателям уже использовал. Результат тот же)
     
  2. gamecreator

    gamecreator Гость

    Может екзешник вызывает функцию другим типом вызова?
     
  3. Yason

    Yason Гость

    К сожалению, я не очень помню размеры разных типов в дельфи, но тут явно нестыковка:

    Upd: посмотрел размеры,
    ULONG ulAddr - 8 байт
    ulAddr:longword - 4 байта

    UINT uiValuesCnt - 4 байта
    uiValuesCnt:word - 2 байта

    ULONG uiDataAddr - 8 байт
    ulDataAddr:Cardinal - 4байта
     
  4. Kosoglaz

    Kosoglaz Гость

    gamecreator, Yason,
    спасибо за советы.
    Буду смотреть в этом направлении.
    Вызов правда везде
    в си:
    #define EXPORTCALLstd extern "C" int __declspec(dllexport) __stdcall;
    EXPORTCALLstd [экспортируемая функция]
    в дельфи:
    [функция (импорт или экспорт)];stdcall;
     
Загрузка...

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