Новичок
Профиль
Группа: Участник
Сообщений: 25
Регистрация: 23.6.2004
Репутация: нет Всего: нет
|
Здравствуйте.Вот код длл-ки написанной на С++. Нужна помощь в переводе на Дельфи. 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. Код во вложенном архиве
Присоединённый файл ( Кол-во скачиваний: 1 )
Project.rar 7,04 Kb
|