Conversion of struct with struct nested to record

2

I have a small "constraint" on a project I'm working on. We received a DLL written in C so we could communicate with readers of that company.  Attached, came an example written in Borland C ++ 6, which works correctly. The problem is to use this DLL with Delhpi XE5. One of the routines returns as a result of its operation a struct that has another nested. Below are the structs as defined in Borland C.

struct stChannelInfo
{
  char ReaderTag[16];
  char ReaderEnabled;
 }

 struct stChannel
 {
   int ReaderNumber;
   struct stChannelInfo *ChannelInfo;
 }  

The routine that receives this struct is this:

stChannels = this->deviceInterface->LookForAvailableChannels(EdDirectorySource->Text.c_str(), iSn, dateTimeStart, dateTimeEnd);  
for(int i = 0; i < stChannels.ReaderNumber; i++)  
 {  
   CLbChannels->Items->Add(stChannels.ChannelInfo[i].ReaderTag);  
 }

I wrote this record which would be the equivalent in Delphi:

type stChannelInfo = record  
 ReaderTag : string[16];    
 readerEnabled : char ;    
end;

type stChannel = record    
 ReaderNumber:integer;  
 ChannelInfo : ^stChannelInfo ;  
end;

And the routine that gets the record in Delphi looks like this:

DadosCanais := LookForAvailableChannels (Pchar(dirroot) , sn , datepickerinicial.DateTime,datepickerfinal.DateTime);
for i := 0 to (DadosCanais.ReaderNumber-1) do
 begin
  Showmessage(DadosCanais.ChannelInfo^.ReaderTag);
  inc(DadosCanais.ChannelInfo);
 end;

By the little bit I understood from Borland C, the le loop of the routine reads the various values of stChannel.ChannelInfo.readerTag , but in Delphi the string I get always loses the first character and is filled with spaces.

The definition of use of the routine according to the manual is this:

/*
 Efetua a busca na base de dados de todos os canais do aparelho
 indicado que possuem dados disponíveis no intervalo selecionado.  
 Version:  
 1.00  
 Parameters:  
 *dataBaseFolder caminho da base de dados  
 serialNumber numero de serie do aparelho  
 firstLogTime timestamp inicial  
 lastLogTime timestamp final  
 Returns:  
 stChannel Retorna uma estrutura com o numero de readers disponíveis e
 seus tags. Em caso de problemas, a estrutura terá o parâmetro 
 "ReaderNumber" zerado.  
*/
struct stChannel LookForAvailableChannels (const char * dataBaseFolder, 
     int serialNumber, double firstLogTime, double lastLogTime)  

How can I access the data of the readers' tags? I can not imagine a way to read these values.

    
asked by anonymous 01.07.2014 / 02:12

1 answer

1

I received from Remy, a help I'm posting here. I adapted slightly to my case but it worked perfectly for this case.

{$POINTERMATH ON}

 Type
  PstChannelInfo = ^stChannelInfo;
  stChannelInfo = record
  ChannelTag: array[0..CHANNEL_TAG_LENGTH-1] of AnsiChar;  // Tag (máx 16 caracteres)
  ChannelEnabled: AnsiChar;  // Habilitado se diferente de "0"
 end;

// Structure with information about channels
 stChannel = record
  ChannelNumber: Integer;  // Número de canais no buffer
  ChannelInfo: PstChannelInfo;  // Buffer com informações dos canais
 end;

 stChannels := Self.deviceInterface.LookForAvailableChannels(PChar(EdDirectorySource.Text), iSn, dateTimeStart, dateTimeEnd);  
 for i := 0 to stChannels.ChannelNumber-1 do   
  begin
   CLbChannels.Items.Add(stChannels.ChannelInfo[i].ChannelTag);  // Add to list the values found  
  end;

Alternatively:

 Type
  PstChannelInfo = ^stChannelInfo;
  stChannelInfo = record
  ChannelTag: array[0..CHANNEL_TAG_LENGTH-1] of AnsiChar;  // Tag (máx 16 caracteres)
  ChannelEnabled: AnsiChar;  // Habilitado se diferente de "0"
 end;

 // Structure with information about channels
  stChannel = record
  ChannelNumber: Integer;  // Número de canais no buffer
  ChannelInfo: PstChannelInfo;  // Buffer com informações dos canais
 end;

 PstChannelInfoList = ^TstChannelInfoList;
 TstChannelInfoList = array[0..MaxInt-1] of stChannelInfo;
 stChannels := Self.deviceInterface.LookForAvailableChannels(PChar(EdDirectorySource.Text), iSn, dateTimeStart, dateTimeEnd);
  for i := 0 to stChannels.ChannelNumber-1 do  
   begin
    CLbChannels.Items.Add(PstChannelInfoList(stChannels.ChannelInfo)^[i].ChannelTag);  // Add to list the values found
   end;
    
16.11.2014 / 15:41