Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 01.02.2008, 15:42   #1
Kosoglaz
Новичок
Джуниор
 
Регистрация: 01.02.2008
Сообщений: 2
По умолчанию Передача данных из VC++ DLL в Delphi App

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

Идея такая, что Delphi App делает запрос DLLке, а та возвращает данные.
Вот код C++
[I]
#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","Apri l","May","June","July","August","Se ptember","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 j,mx;

if(nIndex > 9)
nIndex = 9;

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

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

mx = strlen(szVals[nIndex]);
for(j=0; j < mx; j++)
{
*szVal = szVals[nIndex][j];
szVal++;
}
szVal[j] = '\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\CD T_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,@f Val,@szVal);

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



Такие вот дела. Не пойму, в чём проблемы. А главное, не знаю уже отлаженного решения передачи данных, в т.ч. строковых из СиПП ДЛЛ в Дельфи приложение. Подскажите решение, пожалуйста. А ещё лучше, если объясните суть проблемы, чтобы я мог сам понять как это всё делается и почему не делается.
Спасибо!
Kosoglaz вне форума Ответить с цитированием
Старый 01.02.2008, 16:23   #2
B_N
Новичок
Джуниор
 
Регистрация: 18.01.2008
Сообщений: 1,720
По умолчанию

Вот здесь я не совсем понял, где определяется ItemData:

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

Вариант с параметрами работает, но строковые значения криво возвращаются. Дежучник в Си показывает после вызова из
Дельфи с 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 '

однозначно проблема совместимости строк дельфи и строк C (которые оканчиваются нулем)

Дальше пока не дошел еще..
B_N вне форума Ответить с цитированием
Старый 05.02.2008, 10:53   #3
Kosoglaz
Новичок
Джуниор
 
Регистрация: 01.02.2008
Сообщений: 2
По умолчанию

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

на

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

И всё работает!
Kosoglaz вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Чат, передача данных Патрон Общие вопросы Delphi 1 24.06.2008 09:15
Передача данных Ivanich JavaScript, Ajax 1 29.04.2008 00:25
Передача данных на сервер с помощью Delphi Арес Работа с сетью в Delphi 7 10.03.2008 13:29
Передача данных ChipLink Общие вопросы Delphi 4 06.01.2008 11:28