K
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; nLevelInteger; NameChar; fValDouble; szValChar):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;
Такие вот дела. Не пойму, в чёи проблемы. А главное, не знаю уже отлаженного решения передачи данных, в т.ч. строковых из СиПП ДЛЛ в Дельфи приложение.
Подскажите решение, пожалуйста. А ещё лучше, если объясните суть проблемы, чтобы я мог сам понять как это всё делается и почему не делается.
Спасибо!
Помогите, пожалйста, решить проблему передачи данных между приложением 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; nLevelInteger; NameChar; fValDouble; szValChar):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;
Такие вот дела. Не пойму, в чёи проблемы. А главное, не знаю уже отлаженного решения передачи данных, в т.ч. строковых из СиПП ДЛЛ в Дельфи приложение.
Подскажите решение, пожалуйста. А ещё лучше, если объясните суть проблемы, чтобы я мог сам понять как это всё делается и почему не делается.
Спасибо!