문제

저는 WinCC(Siemens)(SCADA)용 사용자 컨트롤을 작성했습니다.이제 컨트롤에 포인터를 전달하고 싶습니다.이를 수행하는 유일한 방법은 다음과 같습니다.속성에 포인터를 씁니다.

WinCC에는 속성을 설정하는 데 이 방법만 있습니다.

  • SetPropBOOL
  • SetPropChar
  • SetPropDouble
  • SetProp단어

컨트롤의 속성은 데이터 유형으로 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 프로세스 후크)을 디버깅했는데 속성 집합에 주소 값이 할당되는 것을 볼 수 있습니다.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 개체의 주소가 내 컨트롤을 호출한 프로세스 메모리에 없습니다(ollydbg로 디버그).WinCC에는 두 가지 프로그램이 있습니다.시각화를 위한 PDLRT.exe(내 컨트롤 호출) 및 GLOBAL-SCRIPT(Ansi-C) 실행을 위한 SCRIPT.exe.

PDLRT에서 ADO-Object의 포인터 주소에 액세스했습니다.ADO 개체 주소의 C#에서 GCHandle을 호출하면 예외가 발생합니다.(ExecutionEngineException)

도움이 되었습니까?

해결책 2

좋아요,

오래 전에 나는 지원을 요청했습니다. Siemens.

지멘스:로드된 DLL, 컨트롤 등은 애플리케이션(메인) 메모리가 아닌 별도의 메모리에 로드됩니다.DLL, 컨트롤 간의 메모리 주소 공유 ....작동 안됨.모두 분리된 기억을 가지고 있습니다.

감독자.유일한 방법:파이프 또는 기타 통신 구현(TCP/IP, ...).

다른 팁

C #이 C ++에있는 포인터를 통해 포인터를 통해 액세스 할 수 있는지 전혀 알지 못합니다.

에 관계없이,이 : (DWORD)(&autoDB)가 틀렸어, 포인터 의 의 을 무의미한 값으로 놓는다.

포인터의 값, 즉 (DWORD) autoDB가 필요합니다.

또한, SetPropDouble()는 Type double, 즉 부동 소수점 숫자의 값을 허용한다.그것은 (큰) 정수인 포인터를 공유하는 아주 좋은 방법이 아닙니다.몇 가지 다른 표현을 시도해보십시오. 큰 정수에 액세스 할 수없는 경우 문자열이 작동 할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top