Come posso ottenere un oggetto dall'indirizzo del puntatore
Domanda
Ho scritto un controllo utente per WinCC (Siemens) (SCADA). Ora voglio passare un puntatore al controllo. L'unico modo per farlo è: scrivere il puntatore in una proprietà.
WinCC ha solo questo metodo per impostare le proprietà
- .
- setpropbool
- setpropchar
- setpropdoppy
- setpropword
La proprietà dal controllo ha Uint come DataType e utilizzo il metodo SetPropDouble per impostare l'indirizzo da un oggetto.
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 );
.
Ho eseguito il debug del mio controllo (Gancio su WinCC-Process) e vedo che il set di proprietà viene assegnato un valore di indirizzo E.G. 0x03041080.
Ora la domanda: Come posso ottenere l'oggetto in C # (.NET) sull'indirizzo?
My Try lancia un'eccezione: ExecutionenNeexception
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: Ho cambiato il mio codice per utilizzare STRING
WinCC
extern __object* autoDB;
DWORD addr = (DWORD)autoDB;
char sAddr[11];
sprintf( sAddr, "%d\0", addr );
SetPropChar( "PictureName", "ControlName", "DataBaseAddr", sAddr );
.
e c # è ora
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!
}
}
.
.
Altre scoperte!
L'indirizzo dall'oggetto ADO non è nella memoria di processo che ha chiamato il mio controllo (debug con OLLYDBG). WinCC ha due programmi: PDLrt.exe per la visualizzazione (questo sta chiamando il mio controllo) e script.exe per l'esecuzione di Global-Script (ANSI-C).
Da PDLRT, ho accesso all'indirizzo del puntatore da ADO-Object. Con la chiamata GChandle in C # dell'ado-oggetto-indirizzo, l'eccezione viene lanciata. ( ExecutionenGineException )
Soluzione 2
OK,
molto tempo fa e ho chiesto il supporto di Siemens
.
Siemens: i DLL caricati, i controlli e così via vengono caricati in una memoria separata e non nella memoria dell'applicazione (principale).Memory-Indirizzo-Share tra DLL, controlli .... non funziona.Tutti hanno una memoria separata.
super.Unico modo: tubi o altre implementazioni di comunicazione (TCP / IP, ...).
Altri suggerimenti
Non ho idea se C # può accedere attraverso un puntatore in C ++ del genere.
A prescindere, questo: (DWORD)(&autoDB)
è errato, che mette l'indirizzo del puntatore come valore della proprietà, che è inutile.
Hai bisogno del valore del puntatore, I.e. (DWORD) autoDB
.
Inoltre, SetPropDouble()
accetta un valore di tipo double
, I.e. Un numero di virgola mobile.Questo non sarà un modo molto carino per condividere un puntatore, che è un (grande) intero.Prova qualche rappresentazione diversa, la stringa potrebbe funzionare se non hai accesso a un numero intero abbastanza grande.