Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > перевести код с С на дельфи


Автор: Unregistered 1.11.2006, 04:36
Здравствуйте.Вот код длл-ки написанной на С++. Нужна помощь в переводе на Дельфи.
dataserv2.h
Код

#ifndef DATASERV_H
#define DATASERV_H //включить только один раз


//--- Описания структур, используемых для общения с OPC-сервером ---//


#include <string.h>

#pragma pack(push, 1) // Важно!!! Байтовое выравнивание

//---------- Наименование  тега -----------//


struct TTagName
{
  char *name; // собственно наименование

  enum{QualityUsed=0x80000000, QualityGood=0x800000c0, QualityBad=0x80000000};

  TTagName(){name=NULL;};
  ~TTagName() {delete name; name = NULL;};

  void setName( const char *aName )
    {
    delete name;
    if( !aName ) 
        { name = 0; return; };
    name = new char[ strlen( aName ) + 1 ];
    if(name)
      strcpy(name, aName );
    };
};


//----------------------- Аналоговый тег ------------------------//
struct TAnTag : TTagName
{
  float value; // значение параметра в единицах физической величины
  unsigned int OpcQuality;
  TAnTag(){value=0;OpcQuality=0;}
};


//----------------------- Битовый тег ------------------------//
struct TBitTag : TTagName
{
  unsigned char value; // значение параметра (0 или 1)
  unsigned int OpcQuality;
  TBitTag(){value=0;OpcQuality=0;}
};

//----------------------- Целый тег ------------------------//


struct TIntTag : TTagName
{
  int value; // значение параметра 
  unsigned int OpcQuality;
  TIntTag(){value=0;OpcQuality=0;};
};

//----------------- Данные для OPC-сервера --------------------//
struct TDataForOPCServer
{
  unsigned char dataIsValid;   // признак того, что данные корректны
  unsigned short anTagsQnty;   // количество аналоговых тегов
  const TAnTag *anTagsArray;   // указатель на массив аналоговых тегов
  unsigned short bitTagsQnty;  // количество битовых тегов
  const TBitTag *bitTagsArray; // указатель на массив битовых тегов
  unsigned short intTagsQnty;  // количество целых тегов
  const TIntTag *intTagsArray; // указатель на массив целых тегов

  unsigned short structVersionNumber

  char DeviceName[64]; // имя устройства
  char Reserved[128]; // Зарезервировано для будущих модификаций.
                      // (эта память должна быть обнулена)
};


//=============== Функции, вызываемые OPC-сервером: ==============

extern "C"
{

//  1) функция, возвращающая указатель на блок объектовых данных
__declspec( dllexport )
     const TDataForOPCServer * PASCAL GetDataForOPCServer( void );

//   2) функция для изменения значения аналогового тега
__declspec( dllexport )
       unsigned char PASCAL SetAnTagValue(
       unsigned  number, 
       float value           
       );

//   3) функция для изменения значения битового тега
__declspec( dllexport )
       unsigned char PASCAL SetBitTagValue(
       unsigned  number, 
       unsigned char value  
       );

//   4) функция для изменения значения целого тега
__declspec( dllexport )
       unsigned char PASCAL SetIntTagValue(
       unsigned  number, 
       int value    
       );

__declspec( dllexport )
       void PASCAL OnShutDown();
}; // end of extern "C"

#pragma pack(pop) // restore origiunal alignment

#endif

В этом коде мне ничего не понятно.

dataserv2.cpp
Код

#include <windows.h>
#include "dataserv2.h"  // structure version # 2 !!!
#include "opc_codes.h"  
#include <math.h>
#include <process.h>
#include <stdio.h>

#define MAX_TAG 5 

TAnTag AnTag[MAX_TAG*2];
TBitTag BitTag[MAX_TAG*2];
TIntTag IntTag[MAX_TAG*2];

// структура, рассказывающая OPC-серверу, где находятся массивы тегов...

TDataForOPCServer DataForOpc[3]=
{
  {     1,
        MAX_TAG,AnTag,
        MAX_TAG,BitTag,
        MAX_TAG,IntTag, 
        2,  
        "Device1"
  },
  {     1,
        MAX_TAG,AnTag+MAX_TAG,
        MAX_TAG,BitTag+MAX_TAG,
        MAX_TAG,IntTag+MAX_TAG,
        2,    
        "Device2"
  },
  {0}
};
// ... и функция, возвращающая OPC-серверу указатель на эту структуру:


__declspec( dllexport )
const TDataForOPCServer * PASCAL GetDataForOPCServer()
{
  return DataForOpc;
};


//===  Функции изменения тегов разного типа: ==================

//    функция для изменения значения аналогового тега

__declspec( dllexport )
unsigned char PASCAL SetAnTagValue(
       unsigned num, 
       float value            // новое значение параметра
    )

  unsigned short device_no=HIWORD(num);
  unsigned short number=LOWORD(num);

  if(number<0 || number>=MAX_TAG || device_no>1)
      return FALSE;
  AnTag[device_no*MAX_TAG+number].value=value;

    
  return TRUE;
};

//---------------------------------------------------------------------------
//    функция для изменения значения битового тега

__declspec( dllexport )
unsigned char PASCAL SetBitTagValue(
       unsigned num, 
       unsigned char value    // новое значение параметра
       )
  unsigned short device_no=HIWORD(num);
  unsigned short number=LOWORD(num);

  if(number<0 || number>=MAX_TAG || device_no>1) 
      return FALSE;
  BitTag[device_no*MAX_TAG+number].value=value;
    
  return TRUE;
};

//---------------------------------------------------------------------------
//    функция для изменения значения целого тега

__declspec( dllexport )
unsigned char PASCAL SetIntTagValue(
       unsigned num, 
       int value    // новое значение параметра
       )
  unsigned short device_no=HIWORD(num);
  unsigned short number=LOWORD(num);

  if(number<0 || number>=MAX_TAG || device_no>1)
      return FALSE;
  IntTag[device_no*MAX_TAG+number].value=value; 
    
  return TRUE;
};

//---------------------------------------------------------------------------

float Dt= (float)0.003;
float Tt;

// Главная рабочая нить  DLL, в которой должен происходить опрос
// устройства и обновление значений в массивах тегов:

void WorkingThread( void *dummy ) // Thread function
{
  while(1)
  { int i;
    if(IntTag[0].value>0)
      Sleep(IntTag[0].value);
    else Sleep(10);
      

    Tt=Tt+Dt;
    if(Tt>10)
      Tt=Tt-(float)3.1415926*3;

    /*
    for(int k=0;k <2 ; k++) // simulate good/bad
        if(Tt<5)
             DataForOpc[k].dataIsValid=1;
        else DataForOpc[k].dataIsValid=0;
    */

    for(i=1; i != MAX_TAG; i++)  
    {
      // симулируем изменение значений:
      AnTag[i].value= (float)sin(Tt+i);
                 // structure version # 2 !!!:
      AnTag[i].OpcQuality= (AnTag[i].value<0.8)? TTagName::QualityUsed | OPC_QUALITY_GOOD : 
                                               TTagName::QualityUsed | OPC_QUALITY_LAST_USABLE;

      BitTag[i].value= (AnTag[i].value>0)? 1:0;
                 // structure version # 2 !!!:
      BitTag[i].OpcQuality= (AnTag[i].value<0.6)? TTagName::QualityGood : TTagName::QualityBad;

      IntTag[i].value= (int)(AnTag[i].value * 10);
                  // structure version # 2 !!!:
      IntTag[i].OpcQuality= (AnTag[i].value<0.7)? TTagName::QualityGood :
                                                TTagName::QualityUsed | OPC_QUALITY_COMM_FAILURE;
    };
  };
};


//---------------------------------------------------------------------------
// Класс, конструктор которого запускает рабочую нить DLL
// (это можно делать и из DLLEntryPoint по DLL_PROCESS_ATTACH,
// но через конструктор объекта, кажется, удобнее)

class MyWorkingThread
{
 public:

  MyWorkingThread() // Все делает конструктор:
  {

    // Заполняем массив имен тегов для OPC-сервера:
    for(int i=0; i != MAX_TAG*2; i++) // --v.2.0!
                // *2 - для обоих устройств !!!
    {
     char s[64]="";
     char ss[64]="";
     char sss[64]="";

     char* prefix= (i<MAX_TAG/2)? "unit1." : "unit2.";

     sprintf(s,"%sanalog_%d",prefix,i);
     sprintf(ss,"%sbit_%d",prefix,i);
     sprintf(sss,"%sint_%d",prefix,i);
     AnTag[i].setName(s);
     BitTag[i].setName(ss);
     IntTag[i].setName(sss);

     if(i==0) //в нашем примере 0-й целый тег управляет периодом обновления
              // данных в dll - ему даем специальное имя
     {
        IntTag[i].setName("UpdateRate");
        IntTag[i].value=10;// начальное значение

     };
        

    };
    // Создаем рабочую нить:
    _beginthread( WorkingThread, 0, NULL );
  };
};

//=========================================================

/* 
   инициализация статического объекта, конструктор которого 
   сразу после загрузки DLL создает рабочую нить
   (чтобы не возиться с DLLEntryPoint - хотя это, конечно,
   дело разработчика):
*/
MyWorkingThread* mythread=new MyWorkingThread;


Содержимое функций dataserv2.cpp мне более менее понятно. Его переводить не надо. По нему у меня другие вопросы. Куда писать процедуру WorkingThread, что у нее за параметр? Создавать поток или он не нужен? Использовать класс как предлагается выше не хочу, буду работать в DLLEntryPoint. Я пытался сам перевести этот код, но из-за незнания типов и синтаксиса С ничего не добился. Точнее добился (AV).  Буду очень признателен за помощь.  Спасибо.

PS. Код во вложенном архиве

Автор: Quadr0 1.11.2006, 08:17
...

Автор: Unregistered 1.11.2006, 09:06
Спасибо. А что на счет заголовочного файла? в частности: в объявлении структуры TTagName, содержится еще и функция? Ну и вообще по типам переменных...
как правильно объявить экспортируемую функцию:
__declspec( dllexport )
     const TDataForOPCServer * PASCAL GetDataForOPCServer( void );

я так пробовал: 
function GetDataForOPCServer:Pointer;export;stdcall;
верно это, нет?

Автор: Romikgy 1.11.2006, 09:40
Цитата(Unregistered @  1.11.2006,  08:06 Найти цитируемый пост)
структуры TTagName

замени классом 

Автор: bems 1.11.2006, 18:31
Цитата(Unregistered @  1.11.2006,  09:06 Найти цитируемый пост)
__declspec( dllexport )
     const TDataForOPCServer * PASCAL GetDataForOPCServer( void );

stdcall не нада

Автор: Unregistered 2.11.2006, 03:01
Цитата(Romikgy @  1.11.2006,  09:40 Найти цитируемый пост)
замени классом  

От этой структуры потом наследуются другие, которые в свою очередь собираются в массив. Я не знаю, каким образом хост-приложение извлекает элементы массива. не вызовет ли это проблем с неправильным распределением памяти? или тут только пробовать? И если я TTagName сделаю классом, то наверное и другие структуры тоже надо? Не понятно что там за pragma надо оно мне нет?

Автор: Snowy 2.11.2006, 03:28
Страница по конвертации C в Delphi: http://www.delphi-jedi.org/APICONVTEAMS:686301

Автор: Unregistered 3.11.2006, 03:18
Ну спасибо конечно. Только вот времени на чтение всего этого у меня нету, и где там как перевести не понятно. Английским владею не настолько хорошо. Скачал конвертер drBob-а - но он мне бредятину какую-то слепил. из TTagName сделал рекорд. Функцию прописал отдельно и тоже с именем TTagName. Также добавил функцию с именем "if". и пр. и др. Самое ценное, что нашел - эквиваленты типов. Но этого не достаточно. Короче - писец, задача не выполнимая. по крайней мере в ближайшие сроки...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)