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

  • Автор темы Kosoglaz
  • Дата начала
K

Kosoglaz

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

1. Запрос от exe к dll на получение данных
dll:
Код:
#define EXPORTCALLstd extern "C" int __declspec(dllexport) __stdcall;
EXPORTCALLstd SendData(bool bCalculate, TfuncDelphiDataReciever *func)
exe:
Код:
CppFnGetData(true,@DataReciever);
2. Отправка данных из dll в exe
dll: код C++
Код:
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:
Код:
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:
Код:
CppFnSetItemData: function(ulDataAddr:Cardinal; pszType:PChar; Values:PDouble; uiValuesCnt:longword; pszValuesStr:PChar):integer; stdcall;
dll: код C++
Код:
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++

Код:
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++

Код:
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 с указателями на объекты вместо прямого обращения к объектам по указателям уже использовал. Результат тот же)
 
G

gamecreator

#2
Может екзешник вызывает функцию другим типом вызова?
 
Y

Yason

#3
К сожалению, я не очень помню размеры разных типов в дельфи, но тут явно нестыковка:
dll:
int SendItemData(ULONG ulAddr, ULONG ulParent, char* szType, char* szName, char* szDimension, double *Values, UINT uiValuesCnt, char* ValuesStr, char* szDescription, char* szInnerName);

EXPORTCALLstd ChangeItemData(ULONG uiDataAddr, char* szType, double* Values, UINT uiValuesCnt, char* szValuesStr)

exe:
function DataReciever(ulAddr:longword; ulParent:longword; pszName:pChar; pszType:pChar; pszDimension:pChar; Values:pDouble; uiValuesCnt:word; pszValuesStr:pChar; pszDescription:pChar; pszInnerName:pChar):integer;stdcall;

CppFnSetItemData: function(ulDataAddr:Cardinal; pszType:pChar; Values:pDouble; uiValuesCnt:longword; pszValuesStr:pChar):integer; stdcall;

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

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

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

Kosoglaz

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