How can i get an object from pointer-address
Question
i have written a user control for WinCC (Siemens) (SCADA). Now I want to pass a pointer to the control. The only way to do this is: write the pointer to a property.
WinCC has only this methods to set properties
- SetPropBOOL
- SetPropChar
- SetPropDouble
- SetPropWord
The property from control has UInt as datatype and i use the SetPropDouble method to set the address from an object.
WinCC Global Script (ANSI-C)
//autoDB is an ADODB.Connection object
//object* autoDB = __object_create("ADODB.Connection");
extern __object* autoDB;
//SetPropDouble( "PictureName", "ControlName", "PropertyName", (DWORD)(&autoDB) );
SetPropDouble( "PictureName", "ControlName", "PropertyName", (DWORD)autoDB );
I've debug my control (hook on WinCC-process) and i see the property-set becomes assigned an address-value e.g. 0x03041080.
Now the question: How can i get the object in c# (.Net) on the address?
My try throws an exception: ExecutionEngineException
private ADODB.Connection _database;
private IntPtr _ptr = IntPtr.Zero;
public uint DataBase{
get{
return (uint)_ptr;
}
set{
if( value != 0 ){
_ptr = (IntPtr)value;
GCHandle gH = GCHandle.FromIntPtr(_ptr); // THIS LINE THROW THE EXCEPTION
_database = gH.Target;
}
}
}
Ok: i've changed my code to use STRING
WinCC
extern __object* autoDB;
DWORD addr = (DWORD)autoDB;
char sAddr[11];
sprintf( sAddr, "%d\0", addr );
SetPropChar( "PictureName", "ControlName", "DataBaseAddr", sAddr );
And c# is now
private string _lpszDataBaseAddr = "";
public string DataBaseAddr{
get{
return _lpszDataBaseAddr;
}
set{
uint addr;
bool ret = uint.TryParse( value, out addr );
if( ! ret ){
return;
}
IntPtr ptr = (IntPtr)addr;
GCHandle gH = GCHandle.FromIntPtr( ptr ); // THE SAME ERROR!
}
}
Other findings!
The address from the ADO-Object is not in the process-memory who called my control (debug with ollydbg). WinCC has two programs: PDLRT.exe for visualisation (this is calling my control) and SCRIPT.exe for running GLOBAL-SCRIPT (Ansi-C).
From PDLRT, i've access to the pointer-address from ADO-Object. By call GCHandle in C# of the ADO-object-address, the exception is thrown. (ExecutionEngineException)
Solution 2
Ok,
long time ago and I've ask the support from Siemens
.
Siemens: The loaded Dlls, Controls and so on are load in an separated memory and not in the application (main) memory. Memory-Address-Share between Dlls, Controls .... is not working. All have a separated memory.
Super. Only way: Pipes or other communication implementations (TCP/IP, ...).
OTHER TIPS
I have no idea if C# can access through a pointer into C++ like that.
Regardless, this: (DWORD)(&autoDB)
is wrong, that puts the address of the pointer as the property's value, which is pointless.
You need the pointer's value, i.e. (DWORD) autoDB
.
Also, SetPropDouble()
accepts a value of type double
, i.e. a floating-point number. That will not be a very nice way to share a pointer, which is a (large) integer. Try some different representation, string might work if you don't have access to a large enough integer.