Convert struct with nested struct to record

Asked

Viewed 205 times

2

I have a little "hindrance" in a project I’m working on. We received a DLL written in C, in order to communicate with readers of this company. In attachment came an example written in Borland C++ 6, which works correctly. The problem is using this DLL with Delhpi XE5. One of the routines returns as a result of its operation a struct that has another nested. Follow below the structs as defined in Borland C.

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

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

The routine that gets this struct that’s the one:

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 at 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 was 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 I understood of Borland C, the loop le of routine reads the various values of stChannel.ChannelInfo.readerTag, but in Delphi the string I receive always loses the first character and comes filled with spaces.

The definition of routine use 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 could I access Readers tag data? I can’t imagine a way to read these values.

  • Did you find a solution? Poste as an answer to help other people.

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;
  • You can accept your answer.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.