Since I use a lot of different datablocks to read and write from I updated a bit of C# code to use resultsets when requesting data from many datablocks in a single call to (daveconnection).execReadRequest(PDU, resultset).
The problem is, using this code. It seemes like memory is leaking, maybe from the resultset or from the pdu?
After some time I will get an exception.
Do I need to create a resultset before calling execReadRequest or execWriteRequest?
Got this strange exception.
*A first chance exception of type 'System.AccessViolationException' occurred in libnodave.net.dll
System.Transactions Critical: 0 : <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Critical"><TraceIdentifier>http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/Unhandled</TraceIdentifier><Description>Unhandled exception</Description><AppDomain>08006Montering.vshost.exe</AppDomain><Exception><ExceptionType>System.AccessViolationException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>Attempted to read or write protected memory. This is often an indication that other memory is corrupt.</Message><StackTrace> at libnodave.resultSet.daveFreeResults(IntPtr rs)
at libnodave.resultSet.Finalize()</StackTrace><ExceptionString>System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at libnodave.resultSet.daveFreeResults(IntPtr rs)
at libnodave.resultSet.Finalize()</ExceptionString></Exception></TraceRecord>*
Need some help getting rid of memoryleak and exceptions :)
/Mats Eriksson (hendrixv)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I still get an exception after typically around 10 000 read/write operations against PLC. Really don't know if it has to do with the PDU or the resultset.
The exception is:
<code>
System.Transactions Critical: 0 : <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Critical"><TraceIdentifier>http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/Unhandled</TraceIdentifier><Description>Unhandled exception</Description><AppDomain>08006Montering.vshost.exe</AppDomain><Exception><ExceptionType>System.AccessViolationException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>Attempted to read or write protected memory. This is often an indication that other memory is corrupt.</Message><StackTrace> at libnodave.pseudoPointer.daveFree(IntPtr p)
at libnodave.pseudoPointer.Finalize() in C:\Sejfo\PC\08006_Montering\08006Montering\PLC\libnodave.net.cs:line 231</StackTrace><ExceptionString>System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at libnodave.pseudoPointer.daveFree(IntPtr p)
at libnodave.pseudoPointer.Finalize() in C:\Sejfo\PC\08006_Montering\08006Montering\PLC\libnodave.net.cs:line 231</ExceptionString></Exception></TraceRecord>
</code>
Any ideas? =)
I added the code for freeing up memory for the resultset
/Mats
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
do You use any kind of **invoke** to update Your GUI?
I have the same problem as You.
I found out that the invoker leaves its handles open. Depending on the update rate I had about 1k handles in very short time.
The garbage collector cleans them periodically.
I think the problem occurs during the execution of the GC!
When I don't use the invoking to update the GUI and just run the connection in a background task the errors don't occur!
Alex: could it be that libnodave tries to declare the pointer in a memory area that is accesible but the next moment is no longer accessible because of the garbage collection?
Stephan
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
After many tests with libnodave.net and many errors in different places "Attempted to read or write protected memory. This is often an indication that other memory is corrupt",
I believe that problem is time short and cyclic (100ms) (in my case)…
I decided and I did my class ( libnodave.net) without use "pointer" (only using "import") and the problems over…
my suggestion, create your own class….
Alex….
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You mean the libnodave.dll? But it's C - so I have to port it to C#? Hmm, dunno…
I had no chance to check something else out, yet :
I've read lots of articles bout invoke.
Finally I found, that "begininvoke" or "SynchronizationContext" doesn't waste handles like 'invoke' or 'method invoke'.
When I know more, I'll post it here…
Meanwhile thx,
Steph
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi Alex,
how does your class work?
I do not see how to avoid using pointers…
I am no expert in .NET.
The idea of the "pseudopointers" is: the memory is allocated, freed and referenced only in the dll's C-code.
How do you use other dlls written in C from C#?
Thomas (I wrote libnodave)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi,
I've tested it with "SynchronizationContext" for updating the GUI from libnodave running in a background task.
The handle problem is solved, but the pointer problem still occurs - now much later than before - aprox after 2min with 1ms update rate
Intresting, it does not occur when not updating the GUI **and** doin nothing else on the GUI…therefore I have a memory leak…
So Alex,
would You be so kind and give us - or at least me -a small sample of how to get rid of the pointer, please? :-)
Stephan
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi, my class without "pseudopointer", I have tested and until now, no problems…. Its necessary change(adapt) your code…. (some comments in class are portuguese-br)
public class plc
{
/*
This struct contains whatever your Operating System uses to hold an in and outgoing
connection to external devices.
*/
public struct daveOSserialType {public int rfd;public int wfd;}
/*
Protocol types to be used with new daveInterface:
*/
public static readonly int daveProtoMPI=0; /* MPI for S7 300/400 */
public static readonly int daveProtoMPI2 = 1; /* MPI for S7 300/400, "Andrew's version" */
public static readonly int daveProtoMPI3 = 2; /* MPI for S7 300/400, Step 7 Version, experimental */
public static readonly int daveProtoMPI4 = 3; /* MPI for S7 300/400, "Andrew's version" with STX */
public static readonly int daveProtoPPI = 10; /* PPI for S7 200 */
public static readonly int daveProtoAS511 = 20; /* S5 via programming interface */
public static readonly int daveProtoS7online = 50; /* use s7onlinx.dll for transport */
public static readonly int daveProtoISOTCP = 122; /* ISO over TCP */
public static readonly int daveProtoISOTCP243 = 123; /* ISO over TCP with CP243 */
public static readonly int daveProtoMPI_IBH = 223; /* MPI with IBH NetLink MPI to ethernet gateway */
public static readonly int daveProtoPPI_IBH = 224; /* PPI with IBH NetLink PPI to ethernet gateway */
public static readonly int daveProtoUserTransport = 255; /* Libnodave will pass the PDUs of */
/* S7 Communication to user defined */
/* call back functions. */
/*
* ProfiBus speed constants. This is the baudrate on MPI network, NOT between adapter and PC:
*/
public static readonly int daveSpeed9k = 0;
public static readonly int daveSpeed19k = 1;
public static readonly int daveSpeed187k = 2;
public static readonly int daveSpeed500k = 3;
public static readonly int daveSpeed1500k = 4;
public static readonly int daveSpeed45k = 5;
public static readonly int daveSpeed93k = 6;
/*
Some function codes (yet unused ones may be incorrect).
*/
public static readonly int daveFuncOpenS7Connection = 0xF0;
public static readonly int daveFuncRead = 0x04;
public static readonly int daveFuncWrite = 0x05;
public static readonly int daveFuncRequestDownload = 0x1A;
public static readonly int daveFuncDownloadBlock = 0x1B;
public static readonly int daveFuncDownloadEnded = 0x1C;
public static readonly int daveFuncStartUpload = 0x1D;
public static readonly int daveFuncUpload = 0x1E;
public static readonly int daveFuncEndUpload = 0x1F;
public static readonly int daveFuncInsertBlock = 0x28;
/*
S7 specific constants:
*/
public static readonly int daveBlockType_OB = '8';
public static readonly int daveBlockType_DB = 'A';
public static readonly int daveBlockType_SDB = 'B';
public static readonly int daveBlockType_FC = 'C';
public static readonly int daveBlockType_SFC = 'D';
public static readonly int daveBlockType_FB = 'E';
public static readonly int daveBlockType_SFB = 'F';
/*
Use these constants for parameter "area" in daveReadBytes and daveWriteBytes
*/
public static readonly int daveSysInfo = 0x3; /* System info of 200 family */
public static readonly int daveSysFlags = 0x5; /* System flags of 200 family */
public static readonly int daveAnaIn = 0x6; /* analog inputs of 200 family */
public static readonly int daveAnaOut = 0x7; /* analog outputs of 200 family */
public static readonly int daveP = 0x80; /* direct peripheral access */
public static readonly int daveInputs = 0x81;
public static readonly int daveOutputs = 0x82;
public static readonly int daveFlags = 0x83;
public static readonly int daveDB = 0x84; /* data blocks */
public static readonly int daveDI = 0x85; /* instance data blocks */
public static readonly int daveLocal = 0x86; /* not tested */
public static readonly int daveV = 0x87; /* don't know what it is */
public static readonly int daveCounter = 28; /* S7 counters */
public static readonly int daveTimer = 29; /* S7 timers */
public static readonly int daveCounter200 = 30; /* IEC counters (200 family) */
public static readonly int daveTimer200 = 31; /* IEC timers (200 family) */
/**
Library specific:
**/
/*
Result codes. Genarally, 0 means ok,
>0 are results (also errors) reported by the PLC
<0 means error reported by library code.
*/
public static readonly int daveResOK = 0; /* means all ok */
public static readonly int daveResNoPeripheralAtAddress = 1; /* CPU tells there is no peripheral at address */
public static readonly int daveResMultipleBitsNotSupported = 6; /* CPU tells it does not support to read a bit block with a */
/* length other than 1 bit. */
public static readonly int daveResItemNotAvailable200 = 3; /* means a a piece of data is not available in the CPU, e.g. */
/* when trying to read a non existing DB or bit bloc of length<>1 */
/* This code seems to be specific to 200 family. */
public static readonly int daveResItemNotAvailable = 10; /* means a a piece of data is not available in the CPU, e.g. */
/* when trying to read a non existing DB */
public static readonly int daveAddressOutOfRange = 5; /* means the data address is beyond the CPUs address range */
public static readonly int daveWriteDataSizeMismatch = 7; /* means the write data size doesn't fit item size */
public static readonly int daveResCannotEvaluatePDU = -123; /* PDU is not understood by libnodave */
public static readonly int daveResCPUNoData = -124;
public static readonly int daveUnknownError = -125;
public static readonly int daveEmptyResultError = -126;
public static readonly int daveEmptyResultSetError = -127;
public static readonly int daveResUnexpectedFunc = -128;
public static readonly int daveResUnknownDataUnitSize = -129;
public static readonly int daveResShortPacket = -1024;
public static readonly int daveResTimeout = -1025;
/*
Error code to message string conversion:
Call this function to get an explanation for error codes returned by other functions.
*/
/*
public static extern string
daveStrerror(int res);
*/
public static extern IntPtr _daveStrerror(int res);
public static string daveStrerror(int res)
{
return Marshal.PtrToStringAuto(_daveStrerror(res));
}
/*
Copy an internal String into an external string buffer. This is needed to interface
with Visual Basic. Maybe it is helpful elsewhere, too.
C# can well work with C strings.
*/
//EXPORTSPEC void DECL2 daveStringCopy(char * intString, char * extString);
/*
Max number of bytes in a single message.
*/
public static readonly int daveMaxRawLen = 2048;
/*
Some definitions for debugging:
*/
public static readonly int daveDebugRawRead = 0x01; /* Show the single bytes received */
public static readonly int daveDebugSpecialChars = 0x02; /* Show when special chars are read */
public static readonly int daveDebugRawWrite = 0x04; /* Show the single bytes written */
public static readonly int daveDebugListReachables = 0x08; /* Show the steps when determine devices in MPI net */
public static readonly int daveDebugInitAdapter = 0x10; /* Show the steps when Initilizing the MPI adapter */
public static readonly int daveDebugConnect = 0x20; /* Show the steps when connecting a PLC */
public static readonly int daveDebugPacket = 0x40;
public static readonly int daveDebugByte = 0x80;
public static readonly int daveDebugCompare = 0x100;
public static readonly int daveDebugExchange = 0x200;
public static readonly int daveDebugPDU = 0x400; /* debug PDU handling */
public static readonly int daveDebugUpload = 0x800; /* debug PDU loading program blocks from PLC */
public static readonly int daveDebugMPI = 0x1000;
public static readonly int daveDebugPrintErrors = 0x2000; /* Print error messages */
public static readonly int daveDebugPassive = 0x4000;
public static readonly int daveDebugErrorReporting = 0x8000;
public static readonly int daveDebugOpen = 0x10000;
public static readonly int daveDebugAll = 0x1ffff;
/*
set and read debug level:
*/
public static extern void daveSetDebug(int newDebugLevel);
public static extern int daveGetDebug();
public static int daveMPIReachable = 0x30;
public static int daveMPIunused = 0x10;
public static int davePartnerListSize = 126;
/*
This wrapper class is used to avoid dealing with "unsafe" pointers to libnodave
internal structures. More wrapper classes are derived from this for the different
structures. Constructors of derived classes will call functions in libnodave that
allocate internal structures via malloc. The functions used return integers by
declaration. These integers are stored in "pointer" In fact, these integers contain
the "bit patterns" of the pointers. The compiler is deceived about the real nature of
the return values. This is ok as long as the pointers are only used in libnodave,
because libnodave routines are assumed to know what they may do with them.
The destructor here passes the pointers back to libnodave's daveFree to release memory
when the C# object is destructed.
*/
//**********PSEUDOPOINTER***********
protected static extern int daveFree(IntPtr p);
public void freePointer(IntPtr p)//**********ADICIONADO PELA DIGITAL AUTOMATION********
{
try
{
daveFree(p);
}
catch
{
//MessageBox.Show("erro no freePointer");
}
}
protected static extern int daveConnectPLC(IntPtr dc);
public int connectPLC(IntPtr dc)
{
return daveConnectPLC(dc);
}
protected static extern int daveDisconnectPLC(IntPtr dc);
public int disconnectPLC(IntPtr dc)
{
return daveDisconnectPLC(dc);
}
protected static extern int daveReadBytes(IntPtr dc, int area, int DBnumber, int start, int len, byte buffer);
public int readBytes(IntPtr dc,int area, int DBnumber, int start, int len, byte buffer)
{
return daveReadBytes(dc, area, DBnumber, start, len, buffer);
}
protected static extern int daveReadManyBytes(IntPtr dc, int area, int DBnumber, int start, int len, byte buffer);
public int readManyBytes(IntPtr dc, int area, int DBnumber, int start, int len, byte buffer)
{
return daveReadManyBytes(dc, area, DBnumber, start, len, buffer);
}
protected static extern int daveReadBits(IntPtr dc, int area, int DBnumber, int start, int len, byte buffer);
public int readBits(IntPtr dc,int area, int DBnumber, int start, int len, byte buffer)
{
return daveReadBits(dc, area, DBnumber, start, len, buffer);
}
protected static extern int daveWriteBytes(IntPtr dc, int area, int DBnumber, int start, int len, byte buffer);
public int writeBytes(IntPtr dc,int area, int DBnumber, int start, int len, byte buffer)
{
return daveWriteBytes(dc, area, DBnumber, start, len, buffer);
}
protected static extern int daveWriteManyBytes(IntPtr dc, int area, int DBnumber, int start, int len, byte buffer);
public int writeManyBytes(IntPtr dc,int area, int DBnumber, int start, int len, byte buffer)
{
return daveWriteManyBytes(dc, area, DBnumber, start, len, buffer);
}
protected static extern int daveWriteBits(IntPtr dc, int area, int DBnumber, int start, int len, byte buffer);
public int writeBits(IntPtr dc, int area, int DBnumber, int start, int len, byte buffer)
{
return daveWriteBits(dc, area, DBnumber, start, len, buffer);
}
protected static extern int daveGetS32(IntPtr dc);
public int getS32(IntPtr dc)
{
return daveGetS32(dc);
}
protected static extern int daveGetU32(IntPtr dc);
public int getU32(IntPtr dc)
{
return daveGetU32(dc);
}
protected static extern int daveGetS16(IntPtr dc);
public int getS16(IntPtr dc)
{
return daveGetS16(dc);
}
protected static extern int daveGetU16(IntPtr dc);
public int getU16(IntPtr dc)
{
return daveGetU16(dc);
}
protected static extern int daveGetS8(IntPtr dc);
public int getS8(IntPtr dc)
{
return daveGetS8(dc);
}
protected static extern int daveGetU8(IntPtr dc);
public int getU8(IntPtr dc)
{
return daveGetU8(dc);
}
protected static extern int daveGetS32At(IntPtr dc,int pos);
public int getS32At(IntPtr dc,int pos)
{
return daveGetS32At(dc, pos);
}
protected static extern int daveGetU32At(IntPtr dc, int pos);
public int getU32At(IntPtr dc,int pos)
{
return daveGetU32At(dc, pos);
}
protected static extern int daveGetS16At(IntPtr dc, int pos);
public int getS16At(IntPtr dc,int pos)
{
return daveGetS16At(dc, pos);
}
protected static extern int daveGetU16At(IntPtr dc, int pos);
public int getU16At(IntPtr dc,int pos)
{
return daveGetU16At(dc, pos);
}
protected static extern int daveGetS8At(IntPtr dc, int pos);
public int getS8At(IntPtr dc,int pos)
{
return daveGetS8At(dc, pos);
}
protected static extern int daveGetU8At(IntPtr dc, int pos);
public int getU8At(IntPtr dc,int pos)
{
return daveGetU8At(dc, pos);
}
protected static extern float daveGetFloatAt(IntPtr dc, int pos);
public float getFloatAt(IntPtr dc,int pos)
{
return daveGetFloatAt(dc, pos);
}
protected static extern int daveGetCounterValueAt(IntPtr dc, int pos);
public int getCounterValueAt(IntPtr dc,int pos)
{
return daveGetCounterValueAt(dc, pos);
}
protected static extern float daveGetSecondsAt(IntPtr dc, int pos);
public float getSecondsAt(IntPtr dc,int pos)
{
return daveGetSecondsAt(dc, pos);
}
protected static extern int daveGetAnswLen(IntPtr dc);
public int getAnswLen(IntPtr dc)
{
return daveGetAnswLen(dc);
}
protected static extern int daveGetMaxPDULen(IntPtr dc);
public int getMaxPDULen(IntPtr dc)
{
return daveGetMaxPDULen(dc);
}
protected static extern int davePrepareReadRequest(IntPtr dc, IntPtr p);
public int prepareReadRequest(IntPtr dc,IntPtr p)
{
//PDU p=new PDU();
//davePrepareReadRequest(pointer, p.pointer);
//return p;
return davePrepareReadRequest(dc,p);
}
protected static extern int davePrepareWriteRequest(IntPtr dc, IntPtr p);
public int prepareWriteRequest(IntPtr dc,IntPtr p)
{
//PDU p=new PDU();
//davePrepareWriteRequest(pointer, p.pointer);
//return p;
return davePrepareWriteRequest(dc,p);
}
protected static extern int daveExecReadRequest(IntPtr dc, IntPtr p, IntPtr rl);
public int execReadRequest(IntPtr dc, IntPtr p, IntPtr rl)
{
return daveExecReadRequest(dc, p, rl);
}
protected static extern int daveExecWriteRequest(IntPtr dc, IntPtr p, IntPtr rl);
public int execWriteRequest(IntPtr dc, IntPtr p, IntPtr rl)
{
return daveExecWriteRequest(dc, p, rl);
}
protected static extern int daveUseResult(IntPtr dc, IntPtr rs, int number);
public int useResult(IntPtr dc,IntPtr rs, int number)
{
return daveUseResult(dc, rs, number);
}
protected static extern int daveReadSZL(IntPtr dc,int id,int index,byte ddd, int len);
public int readSZL(IntPtr dc,int id,int index,byte ddd, int len)
{
return daveReadSZL(dc,id,index, ddd, len);
}
protected static extern int daveStart(IntPtr dc);
public int start(IntPtr dc)
{
return daveStart(dc);
}
protected static extern int daveStop(IntPtr dc);
public int stop(IntPtr dc)
{
return daveStop(dc);
}
protected static extern int daveForce200(IntPtr dc, int area, int start, int val);
public int force200(IntPtr dc,int area, int start, int val)
{
return daveForce200(dc, area, start, val);
}
protected static extern int daveForceDisconnectIBH(IntPtr dc, int src, int dest, int MPI);
public int forceDisconnectIBH(IntPtr dc,int src, int dest, int MPI)
{
return daveForceDisconnectIBH(dc, src, dest, MPI);
}
protected static extern int daveGetResponse(IntPtr dc);
public int getGetResponse(IntPtr dc)
{
return daveGetResponse(dc);
}
protected static extern int daveSendMessage(IntPtr dc, IntPtr p);
public int getMessage(IntPtr dc, IntPtr p)
{
return daveSendMessage(dc, p);
}
protected static extern int daveGetProgramBlock(IntPtr dc, int blockType, int number, byte buffer, ref int length);
public int getProgramBlock(IntPtr dc,int blockType, int number, byte buffer, ref int length)
{
Console.WriteLine("length:"+length);
int a=daveGetProgramBlock(dc, blockType, number, buffer, ref length);
Console.WriteLine("length:"+length);
return a;
}
protected static extern int daveListBlocksOfType(IntPtr dc, int blockType, byte buffer);
public int ListBlocksOfType(IntPtr dc,int blockType, byte buffer)
{
return daveListBlocksOfType(dc, blockType, buffer);
//return -1;
}
protected static extern void daveAddVarToReadRequest(IntPtr p, int area, int DBnum, int start, int bytes);
public void addVarToReadRequest(IntPtr p,int area, int DBnum, int start, int bytes)
{
daveAddVarToReadRequest(p, area, DBnum, start, bytes);
}
protected static extern void daveAddBitVarToReadRequest(IntPtr p, int area, int DBnum, int start, int bytes);
public void addBitVarToReadRequest(IntPtr p,int area, int DBnum, int start, int bytes)
{
daveAddBitVarToReadRequest(p, area, DBnum, start, bytes);
}
protected static extern void daveAddVarToWriteRequest(IntPtr p, int area, int DBnum, int start, int bytes, byte buffer);
public void addVarToWriteRequest(IntPtr p,int area, int DBnum, int start, int bytes, byte buffer)
{
daveAddVarToWriteRequest(p, area, DBnum, start, bytes, buffer);
}
protected static extern void daveAddBitVarToWriteRequest(IntPtr p, int area, int DBnum, int start, int bytes, byte buffer);
public void addBitVarToWriteRequest(IntPtr p,int area, int DBnum, int start, int bytes, byte buffer)
{
daveAddBitVarToWriteRequest(p, area, DBnum, start, bytes, buffer);
}
protected static extern void daveFreeResults(IntPtr rs);
//******************add Digital Automation*******************
public void freeResult(IntPtr rs)
{
try
{
daveFreeResults(rs);
}
catch
{
//MessageBox.Show("erro no freeResult");
}
}
protected static extern int daveGetErrorOfResult(IntPtr rs, int number);
public int getErrorOfResult(IntPtr rs,int number)
{
return daveGetErrorOfResult(rs, number);
}
//************** CONEXAO *************
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int setPort( string portName, string baud,int parity);
public int SetPort( string portName, string baud,int parity)
{
return setPort(portName,baud,parity);
}
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int openSocket(int port, string portName);
public int OpenSocket(int port, string portName)
{
return openSocket(port,portName);
}
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int openS7online( string portName);
public int OpenS7online( string portName)
{
return openS7online(portName);
}
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int closePort(int port);
public int ClosePort(int port)
{
return closePort(port);
}
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int closeSocket(int port);
public int CloseSocket(int port)
{
return closeSocket(port);
}
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int closeS7online(int port);
public int CloseS7online(int port)
{
return closeS7online(port);
}
protected static extern float toPLCfloat(float f); //*******MUDADO PELA DIGITAL AUTOMATION********
public float toPLCFloat(float f)
{
return toPLCfloat(f);
}
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int daveToPLCfloat(float f);
public int daveToPLCFloat(float f)
{
return daveToPLCfloat(f);
}
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int daveSwapIed_32(int i);
public int SwapIed_32(int i)
{
return daveSwapIed_32(i);
}
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int daveSwapIed_16(int i);
public int SwapIed_16(int i)
{
return daveSwapIed_16(i);
}
//***********FUNÇÕES*************
public static int getS16from(byte b, int pos)
{
if (BitConverter.IsLittleEndian)
{
byte b1=new byte;
b1=b;
b1=b;
return BitConverter.ToInt16(b1, 0);
}
else
return BitConverter.ToInt16(b, pos);
}
public static int getU16from(byte b, int pos)
{
if (BitConverter.IsLittleEndian)
{
byte b1=new byte;
b1=b;
b1=b;
return BitConverter.ToUInt16(b1, 0);
}
else
return BitConverter.ToUInt16(b, pos);
}
public static int getS32from(byte b, int pos)
{
if (BitConverter.IsLittleEndian)
{
byte b1=new byte;
b1=b;
b1=b;
b1=b;
b1=b;
return BitConverter.ToInt32(b1, 0);
}
else
return BitConverter.ToInt32(b, pos);
}
public static uint getU32from(byte b, int pos)
{
if (BitConverter.IsLittleEndian)
{
byte b1=new byte;
b1=b;
b1=b;
b1=b;
b1=b;
return BitConverter.ToUInt32(b1, 0);
}
else
return BitConverter.ToUInt32(b, pos);
}
public static float getFloatfrom(byte b, int pos)
{
if (BitConverter.IsLittleEndian)
{
byte b1=new byte;
b1=b;
b1=b;
b1=b;
b1=b;
return BitConverter.ToSingle(b1, 0);
}
else
return BitConverter.ToSingle(b, pos);
}
private static extern int daveAreaName(int area);
private static extern int daveBlockName(int blockType);
private static extern void daveStringCopy(int i, byte c);
public static string blockName(int blockType)
{
byte s=new byte;
int i=daveBlockName(blockType);
daveStringCopy(i, s);
string st="";
i=0;
while (s_!=0)
{
st=st+(char)s;
i++;
}
return st;
}
public static string areaName(int blockType)
{
byte s=new byte;
int i=daveAreaName(blockType);
daveStringCopy(i, s);
string st="";
i=0;
while (s!=0)
{
st=st+(char)s;
i++;
}
return st;
}
/* Changes:
03/30/2006 bug fix: removed double calls to daveFree in nested destructors.
11/21/2006 bug fix: applied patches from Johann Gail.
Version 0.8.4.5
07/10/09 Added closeSocket()
*/
}
Alex…_
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
thank You very much.
But it's a bit confusing as all the class types are gone as they are methods now…
Dunno exactly how to adapt this.
Nevertheless I'll see what I can do,
Cheers,
Steph
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
o.k. - I finally made it with Your class, Alex - thanks again.
Yes, it seems to work now. As I understand it, You moved the pointers outside the class - but they are still there…;-)
The other thing is, I still have this 'memory leak' - can anyone confirm this?
The used memory grows continuously - in the beginning very fast and after some minutes it slows down - but still grows…
Cheers,
Stephan
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
if I reuse the connection and just exec the 'execReadRequest' in a loop, the loss of memory is minimal.
If I close the connection and free all the pointers etc., the memory is not freed definitvely. If I do that in a loop the memory consumption increases rapidly and is not freed at no time.
Does anybody know what one can do about?
Thx,
Stephan
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Stop All !!!, my class “plc” has a small (minimal) memory leaking….., I haven’t found where is the leaking….
Thomas, I believe that I found the problem of libnova.net.dll…., Ive tested at Windows Vista SP2 and Windows XP SP3 and until now, no errors and no memory leak…., my program test is running with cyclic 100ms(threadpool) with 25 tags(variables of plc)…
I would like that all people test this code below (replace in libnodave.net)….
public class pseudoPointer
{
public IntPtr pointer;//=IntPtr.Zero;
protected static extern int daveFree(IntPtr p);
/* ******************REMOVED by ALEX***********
~pseudoPointer()
{
daveFree(pointer);
}
*/
//****************ADD by ALEX**************
public int freePointer()
{
try
{
if (pointer !=null) //Im not sure if this is necessary, but more one protection
if (pointer != IntPtr.Zero) // check if pointer was used
daveFree(pointer);
return 0; //free OK
}
catch
{
return -1; //free not OK
}
}
//******************ADD by ALEX*******************
protected static extern void daveFreeResults(IntPtr rs);
public int freeResult()
{
try
{
if (pointer !=null) //Im not sure if this is necessary, but more one protection
if (pointer !=IntPtr.Zero) // check if pointer was used
daveFreeResults(pointer);
return 0; //free OK
}
catch
{
return -1; //free not OK
}
}
}
public class resultSet:pseudoPointer
{
protected static extern IntPtr daveNewResultSet();
public resultSet()
{
pointer=daveNewResultSet();
}
protected static extern int daveGetErrorOfResult(IntPtr rs, int number);
public int getErrorOfResult(int number)
{
return daveGetErrorOfResult(pointer, number);
}
}
Alex….
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
hi i got the same probleme describe at the begining of the topic…
And the libnodave.net.dll seems not to integrate these modification.
How can i compile the libnodave.net.cs to get libnodave.net.dll with these modifications ?
Thank you
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
are U still in need of help?
We were talking about the "libnodave.net.cs" file in the "Dot.NET" subfolder of the libnodave source.
Well, it's a C# file … so I dunno if You can include it to Your VB project…
By the way, there's an 'updated' version of libnodave (0.8.4.6) - I didn't try it yet, but probably it has the problem fixed…
Cheers,
Stephan
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am not able to succesfully run multiread. I read all the forums and cant find any help.
I am using VBNET + libnodave.net.dll as reference (I also tried modification by Alex with no effect).[
My code looks like this
quote] Private Sub readmulti1()
Dim p As New libnodave.PDU
Dim rs As New libnodave.resultSet
Dim a1 As Integer
Dim res As Integer
OpenConnection_nodave()
Try
p = dc.prepareReadRequest()
p.addVarToReadRequest(libnodave.daveFlags, 0, 10, 4)
dc.execReadRequest(p, rs)
res = dc.useResult(rs, 0)
Label1.Text = res
If res = 0 Then
a1 = dc.getU8()
Label1.Text = a1.ToString()
Else
MessageBox.Show("error " + res.ToString() + " " + libnodave.daveStrerror(res.ToString()))
End If
CloseConnection_nodave()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
all i get is error -127 cannot work with undefined result set. Any advice?
Connection to PLS i OK, as readbytes function works well.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello
Since I use a lot of different datablocks to read and write from I updated a bit of C# code to use resultsets when requesting data from many datablocks in a single call to (daveconnection).execReadRequest(PDU, resultset).
The problem is, using this code. It seemes like memory is leaking, maybe from the resultset or from the pdu?
After some time I will get an exception.
Do I need to create a resultset before calling execReadRequest or execWriteRequest?
Got this strange exception.
*A first chance exception of type 'System.AccessViolationException' occurred in libnodave.net.dll
System.Transactions Critical: 0 : <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Critical"><TraceIdentifier>http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/Unhandled</TraceIdentifier><Description>Unhandled exception</Description><AppDomain>08006Montering.vshost.exe</AppDomain><Exception><ExceptionType>System.AccessViolationException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>Attempted to read or write protected memory. This is often an indication that other memory is corrupt.</Message><StackTrace> at libnodave.resultSet.daveFreeResults(IntPtr rs)
at libnodave.resultSet.Finalize()</StackTrace><ExceptionString>System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at libnodave.resultSet.daveFreeResults(IntPtr rs)
at libnodave.resultSet.Finalize()</ExceptionString></Exception></TraceRecord>*
Need some help getting rid of memoryleak and exceptions :)
/Mats Eriksson (hendrixv)
I had the same problem, its necessary add the following code in libnodave.net, because this function is “private” :
In: public class resultSet:pseudoPointer……
In:
protected static extern void daveFreeResults(IntPtr rs);
//******ADD THIS CODE*******
public void freeResult(){
try
{
daveFreeResults(pointer);
}
Catch{//}
In your code, add “resultset.freeResult();”
Alex
thanks Alex.. I'll try it and evaluate it. I changed the code in libnodave to:
protected static extern void daveFreeResults(IntPtr rs);
//******ADD THIS CODE*******
public void freeResult()
{
try
{
daveFreeResults(pointer);
}
catch (Exception ex)
{
Console.WriteLine("freeResult exception: " + ex.Message);
}
}
// ~resultSet(){
//// Console.WriteLine("~resultSet(1)");
// daveFreeResults(pointer);
//// Console.WriteLine("~resultSet(2)");
//// daveFree(pointer);
Maybe I should execute davevFree(pointer) also??
:)
/Mats
Mats,
Its too necessary free the "pointer (PDU)", its the same problem of "results", add this code in libnodave.net….
In: public class PDU:pseudoPointer {
protected static extern IntPtr daveNewPDU();
//*********************ADD THIS CODE********************
public void freePDU()
{
try
{
daveFree(pointer);
}
catch
{
//
}
}
in your code, add "PDU.freePDU();"
Alex…
Hello Alex..
It seemes like the PDU gets freed anyway since pseudopointer calls daveFree(pointer) when the c# object gets collected.
/Mats
Hello
I still get an exception after typically around 10 000 read/write operations against PLC. Really don't know if it has to do with the PDU or the resultset.
The exception is:
<code>
System.Transactions Critical: 0 : <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Critical"><TraceIdentifier>http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/Unhandled</TraceIdentifier><Description>Unhandled exception</Description><AppDomain>08006Montering.vshost.exe</AppDomain><Exception><ExceptionType>System.AccessViolationException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>Attempted to read or write protected memory. This is often an indication that other memory is corrupt.</Message><StackTrace> at libnodave.pseudoPointer.daveFree(IntPtr p)
at libnodave.pseudoPointer.Finalize() in C:\Sejfo\PC\08006_Montering\08006Montering\PLC\libnodave.net.cs:line 231</StackTrace><ExceptionString>System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at libnodave.pseudoPointer.daveFree(IntPtr p)
at libnodave.pseudoPointer.Finalize() in C:\Sejfo\PC\08006_Montering\08006Montering\PLC\libnodave.net.cs:line 231</ExceptionString></Exception></TraceRecord>
</code>
Any ideas? =)
I added the code for freeing up memory for the resultset
/Mats
Helo Mats,
try to change in libnodave.net , at "daveFree", put "try and catch"..
Alex….
Hi Mats,
do You use any kind of **invoke** to update Your GUI?
I have the same problem as You.
I found out that the invoker leaves its handles open. Depending on the update rate I had about 1k handles in very short time.
The garbage collector cleans them periodically.
I think the problem occurs during the execution of the GC!
When I don't use the invoking to update the GUI and just run the connection in a background task the errors don't occur!
Alex: could it be that libnodave tries to declare the pointer in a memory area that is accesible but the next moment is no longer accessible because of the garbage collection?
Stephan
Hi Mats and Stephan,
After many tests with libnodave.net and many errors in different places "Attempted to read or write protected memory. This is often an indication that other memory is corrupt",
I believe that problem is time short and cyclic (100ms) (in my case)…
I decided and I did my class ( libnodave.net) without use "pointer" (only using "import") and the problems over…
my suggestion, create your own class….
Alex….
Hi Alex,
You mean the libnodave.dll? But it's C - so I have to port it to C#? Hmm, dunno…
I had no chance to check something else out, yet :
I've read lots of articles bout invoke.
Finally I found, that "begininvoke" or "SynchronizationContext" doesn't waste handles like 'invoke' or 'method invoke'.
When I know more, I'll post it here…
Meanwhile thx,
Steph
Hi Alex,
how does your class work?
I do not see how to avoid using pointers…
I am no expert in .NET.
The idea of the "pseudopointers" is: the memory is allocated, freed and referenced only in the dll's C-code.
How do you use other dlls written in C from C#?
Thomas (I wrote libnodave)
Hello Alex.
Interesting post. When I have time over I'll try your method.
Otherwise you are very welcome to email your .cs file :)
/Mats (mats@autoit.se)
Hi,
I didnt do libnodave.dll, I did libnodave.net.dll, I wrote my class without “pseudopointers”…
Thomas, great idea about to use “pseudopointers”, ….I haven’t found where is the problem, maybe “Synchronization- Mr. Steph wrote”…
Alex…
Hi,
I've tested it with "SynchronizationContext" for updating the GUI from libnodave running in a background task.
The handle problem is solved, but the pointer problem still occurs - now much later than before - aprox after 2min with 1ms update rate
Intresting, it does not occur when not updating the GUI **and** doin nothing else on the GUI…therefore I have a memory leak…
So Alex,
would You be so kind and give us - or at least me -a small sample of how to get rid of the pointer, please? :-)
Stephan
Hi, my class without "pseudopointer", I have tested and until now, no problems…. Its necessary change(adapt) your code…. (some comments in class are portuguese-br)
public class plc
{
/*
This struct contains whatever your Operating System uses to hold an in and outgoing
connection to external devices.
*/
public struct daveOSserialType {public int rfd;public int wfd;}
/*
Protocol types to be used with new daveInterface:
*/
public static readonly int daveProtoMPI=0; /* MPI for S7 300/400 */
public static readonly int daveProtoMPI2 = 1; /* MPI for S7 300/400, "Andrew's version" */
public static readonly int daveProtoMPI3 = 2; /* MPI for S7 300/400, Step 7 Version, experimental */
public static readonly int daveProtoMPI4 = 3; /* MPI for S7 300/400, "Andrew's version" with STX */
public static readonly int daveProtoPPI = 10; /* PPI for S7 200 */
public static readonly int daveProtoAS511 = 20; /* S5 via programming interface */
public static readonly int daveProtoS7online = 50; /* use s7onlinx.dll for transport */
public static readonly int daveProtoISOTCP = 122; /* ISO over TCP */
public static readonly int daveProtoISOTCP243 = 123; /* ISO over TCP with CP243 */
public static readonly int daveProtoMPI_IBH = 223; /* MPI with IBH NetLink MPI to ethernet gateway */
public static readonly int daveProtoPPI_IBH = 224; /* PPI with IBH NetLink PPI to ethernet gateway */
public static readonly int daveProtoUserTransport = 255; /* Libnodave will pass the PDUs of */
/* S7 Communication to user defined */
/* call back functions. */
/*
* ProfiBus speed constants. This is the baudrate on MPI network, NOT between adapter and PC:
*/
public static readonly int daveSpeed9k = 0;
public static readonly int daveSpeed19k = 1;
public static readonly int daveSpeed187k = 2;
public static readonly int daveSpeed500k = 3;
public static readonly int daveSpeed1500k = 4;
public static readonly int daveSpeed45k = 5;
public static readonly int daveSpeed93k = 6;
/*
Some function codes (yet unused ones may be incorrect).
*/
public static readonly int daveFuncOpenS7Connection = 0xF0;
public static readonly int daveFuncRead = 0x04;
public static readonly int daveFuncWrite = 0x05;
public static readonly int daveFuncRequestDownload = 0x1A;
public static readonly int daveFuncDownloadBlock = 0x1B;
public static readonly int daveFuncDownloadEnded = 0x1C;
public static readonly int daveFuncStartUpload = 0x1D;
public static readonly int daveFuncUpload = 0x1E;
public static readonly int daveFuncEndUpload = 0x1F;
public static readonly int daveFuncInsertBlock = 0x28;
/*
S7 specific constants:
*/
public static readonly int daveBlockType_OB = '8';
public static readonly int daveBlockType_DB = 'A';
public static readonly int daveBlockType_SDB = 'B';
public static readonly int daveBlockType_FC = 'C';
public static readonly int daveBlockType_SFC = 'D';
public static readonly int daveBlockType_FB = 'E';
public static readonly int daveBlockType_SFB = 'F';
/*
Use these constants for parameter "area" in daveReadBytes and daveWriteBytes
*/
public static readonly int daveSysInfo = 0x3; /* System info of 200 family */
public static readonly int daveSysFlags = 0x5; /* System flags of 200 family */
public static readonly int daveAnaIn = 0x6; /* analog inputs of 200 family */
public static readonly int daveAnaOut = 0x7; /* analog outputs of 200 family */
public static readonly int daveP = 0x80; /* direct peripheral access */
public static readonly int daveInputs = 0x81;
public static readonly int daveOutputs = 0x82;
public static readonly int daveFlags = 0x83;
public static readonly int daveDB = 0x84; /* data blocks */
public static readonly int daveDI = 0x85; /* instance data blocks */
public static readonly int daveLocal = 0x86; /* not tested */
public static readonly int daveV = 0x87; /* don't know what it is */
public static readonly int daveCounter = 28; /* S7 counters */
public static readonly int daveTimer = 29; /* S7 timers */
public static readonly int daveCounter200 = 30; /* IEC counters (200 family) */
public static readonly int daveTimer200 = 31; /* IEC timers (200 family) */
/**
Library specific:
**/
/*
Result codes. Genarally, 0 means ok,
>0 are results (also errors) reported by the PLC
<0 means error reported by library code.
*/
public static readonly int daveResOK = 0; /* means all ok */
public static readonly int daveResNoPeripheralAtAddress = 1; /* CPU tells there is no peripheral at address */
public static readonly int daveResMultipleBitsNotSupported = 6; /* CPU tells it does not support to read a bit block with a */
/* length other than 1 bit. */
public static readonly int daveResItemNotAvailable200 = 3; /* means a a piece of data is not available in the CPU, e.g. */
/* when trying to read a non existing DB or bit bloc of length<>1 */
/* This code seems to be specific to 200 family. */
public static readonly int daveResItemNotAvailable = 10; /* means a a piece of data is not available in the CPU, e.g. */
/* when trying to read a non existing DB */
public static readonly int daveAddressOutOfRange = 5; /* means the data address is beyond the CPUs address range */
public static readonly int daveWriteDataSizeMismatch = 7; /* means the write data size doesn't fit item size */
public static readonly int daveResCannotEvaluatePDU = -123; /* PDU is not understood by libnodave */
public static readonly int daveResCPUNoData = -124;
public static readonly int daveUnknownError = -125;
public static readonly int daveEmptyResultError = -126;
public static readonly int daveEmptyResultSetError = -127;
public static readonly int daveResUnexpectedFunc = -128;
public static readonly int daveResUnknownDataUnitSize = -129;
public static readonly int daveResShortPacket = -1024;
public static readonly int daveResTimeout = -1025;
/*
Error code to message string conversion:
Call this function to get an explanation for error codes returned by other functions.
*/
/*
public static extern string
daveStrerror(int res);
*/
public static extern IntPtr _daveStrerror(int res);
public static string daveStrerror(int res)
{
return Marshal.PtrToStringAuto(_daveStrerror(res));
}
/*
Copy an internal String into an external string buffer. This is needed to interface
with Visual Basic. Maybe it is helpful elsewhere, too.
C# can well work with C strings.
*/
//EXPORTSPEC void DECL2 daveStringCopy(char * intString, char * extString);
/*
Max number of bytes in a single message.
*/
public static readonly int daveMaxRawLen = 2048;
/*
Some definitions for debugging:
*/
public static readonly int daveDebugRawRead = 0x01; /* Show the single bytes received */
public static readonly int daveDebugSpecialChars = 0x02; /* Show when special chars are read */
public static readonly int daveDebugRawWrite = 0x04; /* Show the single bytes written */
public static readonly int daveDebugListReachables = 0x08; /* Show the steps when determine devices in MPI net */
public static readonly int daveDebugInitAdapter = 0x10; /* Show the steps when Initilizing the MPI adapter */
public static readonly int daveDebugConnect = 0x20; /* Show the steps when connecting a PLC */
public static readonly int daveDebugPacket = 0x40;
public static readonly int daveDebugByte = 0x80;
public static readonly int daveDebugCompare = 0x100;
public static readonly int daveDebugExchange = 0x200;
public static readonly int daveDebugPDU = 0x400; /* debug PDU handling */
public static readonly int daveDebugUpload = 0x800; /* debug PDU loading program blocks from PLC */
public static readonly int daveDebugMPI = 0x1000;
public static readonly int daveDebugPrintErrors = 0x2000; /* Print error messages */
public static readonly int daveDebugPassive = 0x4000;
public static readonly int daveDebugErrorReporting = 0x8000;
public static readonly int daveDebugOpen = 0x10000;
public static readonly int daveDebugAll = 0x1ffff;
/*
set and read debug level:
*/
public static extern void daveSetDebug(int newDebugLevel);
public static extern int daveGetDebug();
public static int daveMPIReachable = 0x30;
public static int daveMPIunused = 0x10;
public static int davePartnerListSize = 126;
/*
This wrapper class is used to avoid dealing with "unsafe" pointers to libnodave
internal structures. More wrapper classes are derived from this for the different
structures. Constructors of derived classes will call functions in libnodave that
allocate internal structures via malloc. The functions used return integers by
declaration. These integers are stored in "pointer" In fact, these integers contain
the "bit patterns" of the pointers. The compiler is deceived about the real nature of
the return values. This is ok as long as the pointers are only used in libnodave,
because libnodave routines are assumed to know what they may do with them.
The destructor here passes the pointers back to libnodave's daveFree to release memory
when the C# object is destructed.
*/
//**********PSEUDOPOINTER***********
protected static extern int daveFree(IntPtr p);
public void freePointer(IntPtr p)//**********ADICIONADO PELA DIGITAL AUTOMATION********
{
try
{
daveFree(p);
}
catch
{
//MessageBox.Show("erro no freePointer");
}
}
//**********daveInterface: pseudoPointer*********
static extern IntPtr daveNewInterface(daveOSserialType fd,string name,int localMPI,int useProto,int speed);
public IntPtr daveInterface(daveOSserialType fd,string name,int localMPI,int useProto,int speed)
{
return daveNewInterface(fd, name, localMPI, useProto, speed);
}
protected static extern int daveInitAdapter(IntPtr di);
public int initAdapter(IntPtr di)
{
return daveInitAdapter(di);
}
protected static extern int daveListReachablePartners(IntPtr di, byte buffer);
public int listReachablePartners(IntPtr di,byte buffer)
{
return daveListReachablePartners(di,buffer);
}
protected static extern void daveSetTimeout(IntPtr di, int time);
public void setTimeout(IntPtr di,int time)
{
daveSetTimeout(di, time);
}
protected static extern int daveGetTimeout(IntPtr di);
public int getTimeout(IntPtr di)
{
return daveGetTimeout(di);
}
protected static extern IntPtr daveDisconnectAdapter(IntPtr di);
public IntPtr disconnectAdapter(IntPtr di)
{
return daveDisconnectAdapter(di);
}
protected static extern string daveGetName(IntPtr di);
public string getName(IntPtr di)
{
return daveGetName(di);
}
//**************daveConnection:pseudoPointer************
protected static extern IntPtr daveNewConnection(IntPtr di,int MPI,int rack,int slot);
public IntPtr daveConnection(IntPtr di,int MPI,int rack,int slot)
{
return daveNewConnection(di, MPI, rack, slot);
}
protected static extern int daveConnectPLC(IntPtr dc);
public int connectPLC(IntPtr dc)
{
return daveConnectPLC(dc);
}
protected static extern int daveDisconnectPLC(IntPtr dc);
public int disconnectPLC(IntPtr dc)
{
return daveDisconnectPLC(dc);
}
protected static extern int daveReadBytes(IntPtr dc, int area, int DBnumber, int start, int len, byte buffer);
public int readBytes(IntPtr dc,int area, int DBnumber, int start, int len, byte buffer)
{
return daveReadBytes(dc, area, DBnumber, start, len, buffer);
}
protected static extern int daveReadManyBytes(IntPtr dc, int area, int DBnumber, int start, int len, byte buffer);
public int readManyBytes(IntPtr dc, int area, int DBnumber, int start, int len, byte buffer)
{
return daveReadManyBytes(dc, area, DBnumber, start, len, buffer);
}
protected static extern int daveReadBits(IntPtr dc, int area, int DBnumber, int start, int len, byte buffer);
public int readBits(IntPtr dc,int area, int DBnumber, int start, int len, byte buffer)
{
return daveReadBits(dc, area, DBnumber, start, len, buffer);
}
protected static extern int daveWriteBytes(IntPtr dc, int area, int DBnumber, int start, int len, byte buffer);
public int writeBytes(IntPtr dc,int area, int DBnumber, int start, int len, byte buffer)
{
return daveWriteBytes(dc, area, DBnumber, start, len, buffer);
}
protected static extern int daveWriteManyBytes(IntPtr dc, int area, int DBnumber, int start, int len, byte buffer);
public int writeManyBytes(IntPtr dc,int area, int DBnumber, int start, int len, byte buffer)
{
return daveWriteManyBytes(dc, area, DBnumber, start, len, buffer);
}
protected static extern int daveWriteBits(IntPtr dc, int area, int DBnumber, int start, int len, byte buffer);
public int writeBits(IntPtr dc, int area, int DBnumber, int start, int len, byte buffer)
{
return daveWriteBits(dc, area, DBnumber, start, len, buffer);
}
protected static extern int daveGetS32(IntPtr dc);
public int getS32(IntPtr dc)
{
return daveGetS32(dc);
}
protected static extern int daveGetU32(IntPtr dc);
public int getU32(IntPtr dc)
{
return daveGetU32(dc);
}
protected static extern int daveGetS16(IntPtr dc);
public int getS16(IntPtr dc)
{
return daveGetS16(dc);
}
protected static extern int daveGetU16(IntPtr dc);
public int getU16(IntPtr dc)
{
return daveGetU16(dc);
}
protected static extern int daveGetS8(IntPtr dc);
public int getS8(IntPtr dc)
{
return daveGetS8(dc);
}
protected static extern int daveGetU8(IntPtr dc);
public int getU8(IntPtr dc)
{
return daveGetU8(dc);
}
protected static extern float daveGetFloat(IntPtr dc);
public float getFloat(IntPtr dc)
{
return daveGetFloat(dc);
}
protected static extern int daveGetCounterValue(IntPtr dc);
public int getCounterValue(IntPtr dc)
{
return daveGetCounterValue(dc);
}
protected static extern float daveGetSeconds(IntPtr dc);
public float getSeconds(IntPtr dc)
{
return daveGetSeconds(dc);
}
protected static extern int daveGetS32At(IntPtr dc,int pos);
public int getS32At(IntPtr dc,int pos)
{
return daveGetS32At(dc, pos);
}
protected static extern int daveGetU32At(IntPtr dc, int pos);
public int getU32At(IntPtr dc,int pos)
{
return daveGetU32At(dc, pos);
}
protected static extern int daveGetS16At(IntPtr dc, int pos);
public int getS16At(IntPtr dc,int pos)
{
return daveGetS16At(dc, pos);
}
protected static extern int daveGetU16At(IntPtr dc, int pos);
public int getU16At(IntPtr dc,int pos)
{
return daveGetU16At(dc, pos);
}
protected static extern int daveGetS8At(IntPtr dc, int pos);
public int getS8At(IntPtr dc,int pos)
{
return daveGetS8At(dc, pos);
}
protected static extern int daveGetU8At(IntPtr dc, int pos);
public int getU8At(IntPtr dc,int pos)
{
return daveGetU8At(dc, pos);
}
protected static extern float daveGetFloatAt(IntPtr dc, int pos);
public float getFloatAt(IntPtr dc,int pos)
{
return daveGetFloatAt(dc, pos);
}
protected static extern int daveGetCounterValueAt(IntPtr dc, int pos);
public int getCounterValueAt(IntPtr dc,int pos)
{
return daveGetCounterValueAt(dc, pos);
}
protected static extern float daveGetSecondsAt(IntPtr dc, int pos);
public float getSecondsAt(IntPtr dc,int pos)
{
return daveGetSecondsAt(dc, pos);
}
protected static extern int daveGetAnswLen(IntPtr dc);
public int getAnswLen(IntPtr dc)
{
return daveGetAnswLen(dc);
}
protected static extern int daveGetMaxPDULen(IntPtr dc);
public int getMaxPDULen(IntPtr dc)
{
return daveGetMaxPDULen(dc);
}
protected static extern int davePrepareReadRequest(IntPtr dc, IntPtr p);
public int prepareReadRequest(IntPtr dc,IntPtr p)
{
//PDU p=new PDU();
//davePrepareReadRequest(pointer, p.pointer);
//return p;
return davePrepareReadRequest(dc,p);
}
protected static extern int davePrepareWriteRequest(IntPtr dc, IntPtr p);
public int prepareWriteRequest(IntPtr dc,IntPtr p)
{
//PDU p=new PDU();
//davePrepareWriteRequest(pointer, p.pointer);
//return p;
return davePrepareWriteRequest(dc,p);
}
protected static extern int daveExecReadRequest(IntPtr dc, IntPtr p, IntPtr rl);
public int execReadRequest(IntPtr dc, IntPtr p, IntPtr rl)
{
return daveExecReadRequest(dc, p, rl);
}
protected static extern int daveExecWriteRequest(IntPtr dc, IntPtr p, IntPtr rl);
public int execWriteRequest(IntPtr dc, IntPtr p, IntPtr rl)
{
return daveExecWriteRequest(dc, p, rl);
}
protected static extern int daveUseResult(IntPtr dc, IntPtr rs, int number);
public int useResult(IntPtr dc,IntPtr rs, int number)
{
return daveUseResult(dc, rs, number);
}
protected static extern int daveReadSZL(IntPtr dc,int id,int index,byte ddd, int len);
public int readSZL(IntPtr dc,int id,int index,byte ddd, int len)
{
return daveReadSZL(dc,id,index, ddd, len);
}
protected static extern int daveStart(IntPtr dc);
public int start(IntPtr dc)
{
return daveStart(dc);
}
protected static extern int daveStop(IntPtr dc);
public int stop(IntPtr dc)
{
return daveStop(dc);
}
protected static extern int daveForce200(IntPtr dc, int area, int start, int val);
public int force200(IntPtr dc,int area, int start, int val)
{
return daveForce200(dc, area, start, val);
}
protected static extern int daveForceDisconnectIBH(IntPtr dc, int src, int dest, int MPI);
public int forceDisconnectIBH(IntPtr dc,int src, int dest, int MPI)
{
return daveForceDisconnectIBH(dc, src, dest, MPI);
}
protected static extern int daveGetResponse(IntPtr dc);
public int getGetResponse(IntPtr dc)
{
return daveGetResponse(dc);
}
protected static extern int daveSendMessage(IntPtr dc, IntPtr p);
public int getMessage(IntPtr dc, IntPtr p)
{
return daveSendMessage(dc, p);
}
protected static extern int daveGetProgramBlock(IntPtr dc, int blockType, int number, byte buffer, ref int length);
public int getProgramBlock(IntPtr dc,int blockType, int number, byte buffer, ref int length)
{
Console.WriteLine("length:"+length);
int a=daveGetProgramBlock(dc, blockType, number, buffer, ref length);
Console.WriteLine("length:"+length);
return a;
}
protected static extern int daveListBlocksOfType(IntPtr dc, int blockType, byte buffer);
public int ListBlocksOfType(IntPtr dc,int blockType, byte buffer)
{
return daveListBlocksOfType(dc, blockType, buffer);
//return -1;
}
//******************PDU:pseudoPointer******************
protected static extern IntPtr daveNewPDU();
public IntPtr PDU()
{
return daveNewPDU();
}
/* ~PDU(){
Console.WriteLine("~PDU()");
daveFree(pointer);
}
*/
protected static extern void daveAddVarToReadRequest(IntPtr p, int area, int DBnum, int start, int bytes);
public void addVarToReadRequest(IntPtr p,int area, int DBnum, int start, int bytes)
{
daveAddVarToReadRequest(p, area, DBnum, start, bytes);
}
protected static extern void daveAddBitVarToReadRequest(IntPtr p, int area, int DBnum, int start, int bytes);
public void addBitVarToReadRequest(IntPtr p,int area, int DBnum, int start, int bytes)
{
daveAddBitVarToReadRequest(p, area, DBnum, start, bytes);
}
protected static extern void daveAddVarToWriteRequest(IntPtr p, int area, int DBnum, int start, int bytes, byte buffer);
public void addVarToWriteRequest(IntPtr p,int area, int DBnum, int start, int bytes, byte buffer)
{
daveAddVarToWriteRequest(p, area, DBnum, start, bytes, buffer);
}
protected static extern void daveAddBitVarToWriteRequest(IntPtr p, int area, int DBnum, int start, int bytes, byte buffer);
public void addBitVarToWriteRequest(IntPtr p,int area, int DBnum, int start, int bytes, byte buffer)
{
daveAddBitVarToWriteRequest(p, area, DBnum, start, bytes, buffer);
}
//********************resultSet:pseudoPointer******************
protected static extern IntPtr daveNewResultSet();
public IntPtr resultSet()
{
return daveNewResultSet();
}
protected static extern void daveFreeResults(IntPtr rs);
//******************add Digital Automation*******************
public void freeResult(IntPtr rs)
{
try
{
daveFreeResults(rs);
}
catch
{
//MessageBox.Show("erro no freeResult");
}
}
protected static extern int daveGetErrorOfResult(IntPtr rs, int number);
public int getErrorOfResult(IntPtr rs,int number)
{
return daveGetErrorOfResult(rs, number);
}
//************** CONEXAO *************
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int setPort( string portName, string baud,int parity);
public int SetPort( string portName, string baud,int parity)
{
return setPort(portName,baud,parity);
}
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int openSocket(int port, string portName);
public int OpenSocket(int port, string portName)
{
return openSocket(port,portName);
}
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int openS7online( string portName);
public int OpenS7online( string portName)
{
return openS7online(portName);
}
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int closePort(int port);
public int ClosePort(int port)
{
return closePort(port);
}
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int closeSocket(int port);
public int CloseSocket(int port)
{
return closeSocket(port);
}
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int closeS7online(int port);
public int CloseS7online(int port)
{
return closeS7online(port);
}
protected static extern float toPLCfloat(float f); //*******MUDADO PELA DIGITAL AUTOMATION********
public float toPLCFloat(float f)
{
return toPLCfloat(f);
}
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int daveToPLCfloat(float f);
public int daveToPLCFloat(float f)
{
return daveToPLCfloat(f);
}
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int daveSwapIed_32(int i);
public int SwapIed_32(int i)
{
return daveSwapIed_32(i);
}
//*******MUDADO PELA DIGITAL AUTOMATION********
protected static extern int daveSwapIed_16(int i);
public int SwapIed_16(int i)
{
return daveSwapIed_16(i);
}
//***********FUNÇÕES*************
public static int getS16from(byte b, int pos)
{
if (BitConverter.IsLittleEndian)
{
byte b1=new byte;
b1=b;
b1=b;
return BitConverter.ToInt16(b1, 0);
}
else
return BitConverter.ToInt16(b, pos);
}
public static int getU16from(byte b, int pos)
{
if (BitConverter.IsLittleEndian)
{
byte b1=new byte;
b1=b;
b1=b;
return BitConverter.ToUInt16(b1, 0);
}
else
return BitConverter.ToUInt16(b, pos);
}
public static int getS32from(byte b, int pos)
{
if (BitConverter.IsLittleEndian)
{
byte b1=new byte;
b1=b;
b1=b;
b1=b;
b1=b;
return BitConverter.ToInt32(b1, 0);
}
else
return BitConverter.ToInt32(b, pos);
}
public static uint getU32from(byte b, int pos)
{
if (BitConverter.IsLittleEndian)
{
byte b1=new byte;
b1=b;
b1=b;
b1=b;
b1=b;
return BitConverter.ToUInt32(b1, 0);
}
else
return BitConverter.ToUInt32(b, pos);
}
public static float getFloatfrom(byte b, int pos)
{
if (BitConverter.IsLittleEndian)
{
byte b1=new byte;
b1=b;
b1=b;
b1=b;
b1=b;
return BitConverter.ToSingle(b1, 0);
}
else
return BitConverter.ToSingle(b, pos);
}
private static extern int daveAreaName(int area);
private static extern int daveBlockName(int blockType);
private static extern void daveStringCopy(int i, byte c);
public static string blockName(int blockType)
{
byte s=new byte;
int i=daveBlockName(blockType);
daveStringCopy(i, s);
string st="";
i=0;
while (s_!=0)
{
st=st+(char)s;
i++;
}
return st;
}
public static string areaName(int blockType)
{
byte s=new byte;
int i=daveAreaName(blockType);
daveStringCopy(i, s);
string st="";
i=0;
while (s!=0)
{
st=st+(char)s;
i++;
}
return st;
}
/* Changes:
03/30/2006 bug fix: removed double calls to daveFree in nested destructors.
11/21/2006 bug fix: applied patches from Johann Gail.
Version 0.8.4.5
07/10/09 Added closeSocket()
*/
}
Alex…_
Hi Alex,
thank You very much.
But it's a bit confusing as all the class types are gone as they are methods now…
Dunno exactly how to adapt this.
Nevertheless I'll see what I can do,
Cheers,
Steph
Hello again,
o.k. - I finally made it with Your class, Alex - thanks again.
Yes, it seems to work now. As I understand it, You moved the pointers outside the class - but they are still there…;-)
The other thing is, I still have this 'memory leak' - can anyone confirm this?
The used memory grows continuously - in the beginning very fast and after some minutes it slows down - but still grows…
Cheers,
Stephan
Hi,
if I reuse the connection and just exec the 'execReadRequest' in a loop, the loss of memory is minimal.
If I close the connection and free all the pointers etc., the memory is not freed definitvely. If I do that in a loop the memory consumption increases rapidly and is not freed at no time.
Does anybody know what one can do about?
Thx,
Stephan
Hi,
Stop All !!!, my class “plc” has a small (minimal) memory leaking….., I haven’t found where is the leaking….
Thomas, I believe that I found the problem of libnova.net.dll…., Ive tested at Windows Vista SP2 and Windows XP SP3 and until now, no errors and no memory leak…., my program test is running with cyclic 100ms(threadpool) with 25 tags(variables of plc)…
I would like that all people test this code below (replace in libnodave.net)….
public class pseudoPointer
{
public IntPtr pointer;//=IntPtr.Zero;
protected static extern int daveFree(IntPtr p);
/* ******************REMOVED by ALEX***********
~pseudoPointer()
{
daveFree(pointer);
}
*/
//****************ADD by ALEX**************
public int freePointer()
{
try
{
if (pointer !=null) //Im not sure if this is necessary, but more one protection
if (pointer != IntPtr.Zero) // check if pointer was used
daveFree(pointer);
return 0; //free OK
}
catch
{
return -1; //free not OK
}
}
//******************ADD by ALEX*******************
protected static extern void daveFreeResults(IntPtr rs);
public int freeResult()
{
try
{
if (pointer !=null) //Im not sure if this is necessary, but more one protection
if (pointer !=IntPtr.Zero) // check if pointer was used
daveFreeResults(pointer);
return 0; //free OK
}
catch
{
return -1; //free not OK
}
}
}
public class resultSet:pseudoPointer
{
protected static extern IntPtr daveNewResultSet();
public resultSet()
{
pointer=daveNewResultSet();
}
// *****************REMOVED by ALEX************
//
//protected static extern void daveFreeResults(IntPtr rs);
// ~resultSet()
// {
// daveFreeResults(pointer);
// }
protected static extern int daveGetErrorOfResult(IntPtr rs, int number);
public int getErrorOfResult(int number)
{
return daveGetErrorOfResult(pointer, number);
}
}
Alex….
Yeah, You've got it! :-)
Thanx a lot, Alex.
Cheers,
Stephan
hi i got the same probleme describe at the begining of the topic…
And the libnodave.net.dll seems not to integrate these modification.
How can i compile the libnodave.net.cs to get libnodave.net.dll with these modifications ?
Thank you
i precise i am using vb.net (2010 express)
Hi got_fr,
are U still in need of help?
We were talking about the "libnodave.net.cs" file in the "Dot.NET" subfolder of the libnodave source.
Well, it's a C# file … so I dunno if You can include it to Your VB project…
By the way, there's an 'updated' version of libnodave (0.8.4.6) - I didn't try it yet, but probably it has the problem fixed…
Cheers,
Stephan
Hello,
I am not able to succesfully run multiread. I read all the forums and cant find any help.
I am using VBNET + libnodave.net.dll as reference (I also tried modification by Alex with no effect).[
My code looks like this
quote] Private Sub readmulti1()
Dim p As New libnodave.PDU
Dim rs As New libnodave.resultSet
Dim a1 As Integer
Dim res As Integer
OpenConnection_nodave()
Try
p = dc.prepareReadRequest()
p.addVarToReadRequest(libnodave.daveFlags, 0, 10, 4)
dc.execReadRequest(p, rs)
res = dc.useResult(rs, 0)
Label1.Text = res
If res = 0 Then
a1 = dc.getU8()
Label1.Text = a1.ToString()
Else
MessageBox.Show("error " + res.ToString() + " " + libnodave.daveStrerror(res.ToString()))
End If
CloseConnection_nodave()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
all i get is error -127 cannot work with undefined result set. Any advice?
Connection to PLS i OK, as readbytes function works well.
my mistake, i figured out that i accidentaly forgot to add dc.ConnectPLC() function :)
now it works fine.