如何从指针地址获取对象

时间:2014-06-04 09:37:39

标签: c# c scada

我为WinCC(西门子)(SCADA)编写了一个用户控件。现在我想传递一个指向控件的指针。唯一的方法是:将指针写入属性。

WinCC只有这些方法来设置属性

  • SetPropBOOL
  • SetPropChar
  • SetPropDouble
  • SetPropWord

来自控件的属性具有UInt作为数据类型,我使用SetPropDouble方法设置对象的地址。

WinCC全局脚本(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 );

我已经调试了我的控件(在WinCC-process上挂钩),我看到属性集被分配了一个地址值,例如0x03041080。

现在的问题是:如何在地址上获取c#(。Net)中的对象?

我的尝试抛出异常: 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;
        }
    }
}

好的:我已将我的代码更改为使用STRING

的WinCC

extern __object* autoDB;
DWORD addr = (DWORD)autoDB;
char sAddr[11];
sprintf( sAddr, "%d\0", addr );
SetPropChar( "PictureName", "ControlName", "DataBaseAddr", sAddr );

而c#现在是

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!
    }
}

其他调查结果!

ADO-Object中的地址不在调用我的控件的进程内存中(使用ollydbg调试)。 WinCC有两个程序:用于可视化的PDLRT.exe(这是调用我的控件)和用于运行GLOBAL-SCRIPT(Ansi-C)的SCRIPT.exe。

从PDLRT,我可以访问ADO-Object的指针地址。通过在ADO对象地址的C#中调用GCHandle,抛出异常。 (的 ExecutionEngineException

2 个答案:

答案 0 :(得分:3)

我不知道C#是否可以通过指向C ++的指针进行访问。

无论如何:(DWORD)(&autoDB)是错误的,它将指针的地址作为属性的值,这是毫无意义的。

您需要指针的值,即(DWORD) autoDB

此外,SetPropDouble()接受double类型的值,即浮点数。这不是一个非常好的共享指针的方法,它是一个(大)整数。尝试一些不同的表示,如果您无法访问足够大的整数,字符串可能会起作用。

答案 1 :(得分:0)

好吧

很久以前,我已经向Siemens寻求支持。

西门子:已加载的Dll,控件等加载在单独的内存中,而不是应用程序(主)内存中。 DLL,控件...之间的内存地址共享不起作用。所有人都有独立的记忆。

超级。唯一方法:管道或其他通信实现(TCP / IP,...)。