Quelltext /~heha/messtech/matdde.zip/source/ddepoke/ddepoke.cpp

//+++++++++++++++++++++++++++++++
// +++++ DDEPoke for MATLAB 16bit

#include <windows.h>
#include <ddeml.h>
#include <stdlib.h>	//fuer _gcvt()
#include <string.h>	//strlen()

#define DLLMEX
extern "C"
{
   #include "..\header\mex.h"
   #include "..\header\testargs.h"
}

#include "..\header\fastdde.h"

#pragma hdrstop


#define ARGS_IN_MIN 3
#define ARGS_IN_MAX 5

#define ARG1_IN	     prhs[0]	 //channel
#define ARG2_IN	     prhs[1]	 //item
#define ARG3_IN	     prhs[2]	 //data
#define ARG4_IN	     prhs[3]	 //cbFormat
#define ARG5_IN	     prhs[4]	 //timeout

#define ARG1_OUT  plhs[0]     //return code


extern "C" void mexFunction(
	int	nlhs,
	Matrix	*plhs[],
	int	nrhs,
	Matrix	*prhs[]
	)

{
   DWORD timeout     = TIMEOUT;
   WORD	 cbFormat = CF_TEXT;  //default

    double  Result = 0;

   if (	 TestIOArgs( nrhs, ARGS_IN_MIN, ARGS_IN_MAX ) &&    //alle erforderlichen Parameter angegeben?
	 TestChannelArg( ARG1_IN ) &&		      //Channel-Argument ok?
	 TestItemArg( ARG2_IN ) )		      //Item-Argument ok?
   {
      if ( nrhs >= ARGS_IN_MAX - 1 )			 //4. Parameter (Clipboard-Format)?
      {
	 cbFormat = TestFormatArg( ARG4_IN, NO_CHK_STR_FORMAT, NULL );
	 if ( nrhs == ARGS_IN_MAX )		      //5. Parameter (TimeOut)?
	    timeout = TestTimeoutArg( ARG5_IN );
      }

      if (cbFormat != (WORD)-1 &&			 //sind bei ungueltigen Argumenten
	 timeout != (DWORD)-1 )			   // -1
      {
	 int		n;
	 DWORD	     hChannel[2];   //2 mal 32 bit
	 PokeFuncParam	FParam;

	   hmemcpy( (char*)hChannel, (char huge*)mxGetPr(ARG1_IN), sizeof(double) );

      //Struktur zur Parameteruebergabe an Unterfunktion fuellen
	 FParam.hConv	= hChannel[0];
	 FParam.idInst	= hChannel[1];
	 FParam.cbFormat   = cbFormat;
	 FParam.timeout = timeout;
	 FParam.Data_Matrix = ARG3_IN;

	 char* szItem = (char*) mxCalloc( n= (int)mxGetN(ARG2_IN) + 1, sizeof(char) );
	 if ( szItem )
	 {
	    mxGetString( ARG2_IN, szItem, n );
	    FParam.hszItem = DdeCreateStringHandle( FParam.idInst, szItem, CP_WINANSI );
	    mxFree( szItem );

	    if ( FParam.hszItem )
	    {

	    //Absprung in Abhaengigkeit des gewaehlten Clipboard-Formates
		 if ( cbFormat == CF_TEXT )	// CF_TEXT Format
	       {
		     if ( CFTextPoke( &FParam ) )
		     Result = (double)1;
	       }
		 else				// Excel Format
	       {
		  if ( FastDDEPoke( &FParam ) )
		     Result = (double)1;
	       }

	       DdeFreeStringHandle ( FParam.idInst, FParam.hszItem );
	    }
	    else
	       HandleDdeError(DdeGetLastError(FParam.idInst));
	 }
	 else
	 {
	    mexPrintf( "???  Memory allocation error.\r\n" );
	    ErrorBeep();
	 }
      }
   }

   ARG1_OUT = mxCreateFull(1, 1, REAL);
   hmemcpy( (char huge*)mxGetPr(ARG1_OUT), (char*)&Result, sizeof(double) );
}




/////////////////////////////////////////////////////////////////////////////////////////////////////

BOOL CFTextPoke( PokeFuncParam* FParam )
{
   HDDEDATA hTrans;	//Ergebnis der DDE Transaktion
   HGLOBAL     hGlobal; //Handle auf freien Speicherbereich

   DWORD maxLength;
   DWORD rows, columns;

   rows	 = (DWORD) mxGetM( FParam->Data_Matrix );
   columns  = (DWORD) mxGetN( FParam->Data_Matrix );

   if (mxIsString(FParam->Data_Matrix))	{
    maxLength=(columns+2)*rows -1;  /* jede Zeile mit 0D0A abgeschlossen, die letzte mit 00 */
    hGlobal=GlobalAlloc(0,maxLength);
    if (!hGlobal) {
     mexPrintf( __FILE__ "??? Memory allocation error.\r\n" );
     ErrorBeep();
    }
    char huge *dst=GlobalLock(hGlobal);
    double huge *src=mxGetPr(FParam->Data_Matrix);

    for (;rows--;) {
     for (;columns--;) {
      *dst++=(char)*src++;
     }
     if (rows) {
      *dst++='\r';
      *dst++='\n';
     }else{
      *dst++='\0';
     }
    }
    GlobalUnlock(hGlobal);

    hTrans = DdeClientTransaction( GlobalLock(hGlobal), maxLength, FParam->hConv, FParam->hszItem,
			   FParam->cbFormat, XTYP_POKE, FParam->timeout, NULL );
   }else{

//zwischen den Strings darf keine null stehen, nur TAB oder CR+LF
//maximale Laenge der in Strings konvertierten Matrix (in bytes)
     maxLength = rows*columns*((DWORD)(CVT_DIGITS + 10));   //... + 10 fuer '\0', E+10 usw.
     maxLength += rows*(columns-1); //Tabs am Spaltenende
     maxLength += 2*rows;	 //CR+LF am Zeilenende

//Speicher fuer eine Zahl
    char* cvtString  = (char*)mxCalloc( CVT_DIGITS + 10, sizeof(char) );   //... + 10 fuer '\0', E+10 usw.

//Speicher reservieren
    hGlobal = GlobalAlloc( GPTR, maxLength+1 ); //+1, damit am Ende immer eine null stehen kann

    if ( !cvtString || !hGlobal )
    {
      mexPrintf( "??? Memory allocation error.\r\n" );
      ErrorBeep();
      if ( cvtString ) mxFree( cvtString );
      if ( hGlobal ) GlobalFree( hGlobal );
      return FALSE;
    }

     char huge* hData	= GlobalLock( hGlobal );
    char huge* dest	= hData;

//Zeiger auf MATLAB-Matrix holen
    double huge* src = (double huge*)mxGetPr( FParam->Data_Matrix );


     int count;		   //StringLaenge ohne abschliessende null
    DWORD index = 0;	//Index zum Zugriff auf MATLAB-Matrix
    DWORD realLength = 0;  //reale Stringlaenge (d.h. evtl. ohne Vorzeichen usw.)

//Matrix transponieren
    for ( int i = 0; i < (int)rows; i++ )
    {
      index = (DWORD)i;
      for ( int k = 0; k < (int)columns; k++ )
      {
	    // index = (DWORD)i+ ((DWORD)k * (DWORD)rows);  //schneller: siehe 2 Zeilen weiter
	 count = StringConvert( cvtString, src[index] );
	 index += (DWORD)rows;

	 hmemcpy( (char huge*)dest, (char*)cvtString, count );

	 dest += count;
	 *dest++ = '\t';	 //Spaltenende
	 realLength += (count+1);   //count + einen Tabulator
      }
      dest--;
      *dest++ = '\r';	      //Zeilenende
      *dest++ = '\n';
      realLength++;
    }
    *dest = '\0';	//abschliessende Null

    mxFree( cvtString );

    hTrans = DdeClientTransaction( hData, realLength+1, FParam->hConv, FParam->hszItem,
			   FParam->cbFormat, XTYP_POKE, FParam->timeout, NULL );
   }

   GlobalUnlock( hGlobal );
   GlobalFree( hGlobal );

   return (BOOL)hTrans;
}



/////////////////////////////////////////////////////////////////////////////////////////////////////
_inline int StringConvert( char* cvtString, double value )
{

//double -> string
   _gcvt( value, CVT_DIGITS, cvtString );

   return strlen( cvtString );	 //= Laenge ohne StringEnde-Null
}



/////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL FastDDEPoke( PokeFuncParam* FParam )
{
   HDDEDATA hTrans;
   HDDEDATA hData;

    FastDDEMemValues DDEMemVal;

   DWORD DBLength;	      //Laenge der gesamten DDE-Transaktion in Bytes
   long MSize;		   //Anzahl der Matrix-Elemente

//Struktur zur Uebergabe an FastDDEMem()
    DDEMemVal.hPr = (double huge*) mxGetPr( FParam->Data_Matrix );
   DDEMemVal.rows = (int) mxGetM( FParam->Data_Matrix );
   DDEMemVal.columns = (int) mxGetN( FParam->Data_Matrix );
   DDEMemVal.quot = 0;

//Laenge in Bytes fuer alle tdtx-Header berechnen
   MSize = (long)DDEMemVal.rows * (long)DDEMemVal.columns;

   while ( (MSize - maxData) >= 0 )	     // => quot=MSize/maxData und rem=MSize%maxData
   {
      DDEMemVal.quot++;
	MSize -= maxData;
   }
   DDEMemVal.offset = 8 + (DDEMemVal.quot * 4); //tdtTableLaenge + (quot * tdtFloatLaenge)
    DDEMemVal.rem = (int)MSize;
    if ( DDEMemVal.rem != 0 )
      DDEMemVal.offset += 4;		     //tdtFloat-Header fuer letzten tdtFloat-Block
//Laenge in DDEMemVal.offset gespeichert


//Laenge der gesamten DDE-Transaktion in Bytes
   DBLength = (DWORD)DDEMemVal.offset + ((DWORD)DDEMemVal.rows * (DWORD)DDEMemVal.columns * sizeof(double));

   hData = DdeCreateDataHandle( FParam->idInst, NULL, DBLength, 0, FParam->hszItem, FParam->cbFormat, NULL );
   if ( !hData )
   {
      HandleDdeError(DdeGetLastError(FParam->idInst));
      return FALSE;
   }

   DDEMemVal.hDataBlock = DdeAccessData( hData, NULL );
   FastDDEMem( &DDEMemVal );  //Erstellen der kompletten Datenstruktur
   DdeUnaccessData( hData );

   hTrans = DdeClientTransaction( (LPBYTE) hData, (DWORD) -1, FParam->hConv, FParam->hszItem,
			   FParam->cbFormat, XTYP_POKE, FParam->timeout, NULL );

   DdeFreeDataHandle( hData );

   return (BOOL)hTrans;
}



/////////////////////////////////////////////////////////////////////////////////////////////////////
void FastDDEMem( FastDDEMemValues* DDEMemVal )
{

   WORD tdtTable_block[] = {tdtTable, 4, DDEMemVal->rows, DDEMemVal->columns};
    WORD tdtFloat_block[] = {tdtFloat, maxData * sizeof(double)};
    WORD tdtFloat_last_block[] = {tdtFloat, DDEMemVal->rem * sizeof(double)};


// *** tdtTable Block kopieren und StartPointer anpassen
   hmemcpy( (char*)DDEMemVal->hDataBlock, (char*)tdtTable_block, sizeof(tdtTable_block) );
    DDEMemVal->hDataBlock += sizeof(tdtTable_block);

   if ( DDEMemVal->quot == 0 )	    //Datenmenge < maxData
   {
      hmemcpy( (char*)DDEMemVal->hDataBlock, (char*)tdtFloat_last_block, sizeof(tdtFloat_last_block) );
      DDEMemVal->hDataBlock += sizeof(tdtFloat_last_block);
   }
   else			   //Datenmenge >= maxData
   {
      hmemcpy( (char*)DDEMemVal->hDataBlock, (char*)tdtFloat_block, sizeof(tdtFloat_block) );
      DDEMemVal->hDataBlock += sizeof(tdtFloat_block);
   }

   BYTE* dest  = (BYTE*)DDEMemVal->hDataBlock;	      //transponierte Matrix
   double huge* src = (double huge*)DDEMemVal->hPr;   //MATLAB-Matrix

   double value;
    int l_quot = 0;
    int loop = 0;
   DWORD index = 0;

// *** Matrix transponieren
   for ( int i = 0; i < DDEMemVal->rows; i++ )
   {
      for ( int k = 0; k < DDEMemVal->columns; k++ )
      {
//Einfuegen der tdtFloat-Header nach Aufteilung in Datenbloecke der Groesse maxData
	 if ( loop == maxData )	    //nach maxData Werten...
	 {
	    l_quot++;		 //l_quot maxDataDatenbloecke
	    loop = 0;		    //neuer Datenblock wird begonnen

	    if ( l_quot < DDEMemVal->quot )	      //sind noch maxData-Datenbloecke vorhanden?
	    {
	       hmemcpy( (char*)dest, (char*)tdtFloat_block, sizeof(tdtFloat_block) );
	       dest += sizeof(tdtFloat_block);	//dann tdtFloat-Header einfuegen
	    }
	    else
	    {
	       hmemcpy( (char*)dest, (char*)tdtFloat_last_block, sizeof(tdtFloat_last_block) );
	       dest += sizeof(tdtFloat_last_block);   //dann letzten tdtFloat-Header einfuegen
	    }

	 }
//Ende der Header-Einfuege-Routine
	 loop++;

	    index = (DWORD)i+ ((DWORD)k * (DWORD)DDEMemVal->rows);
	 value = src[index];
	 hmemcpy( (char*)dest, (char*)&value, sizeof(double) );
	 dest += sizeof(double);
      }
   }
}
Vorgefundene Kodierung: UTF-80