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 )

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top