您可以尝试在功能块周围制作一个包装器:
FUNCTION_BLOCK FINAL FinalBlock
VAR_IN_OUT
someVar: DINT;
END_VAR
FUNCTION_BLOCK Wrapper
VAR_IN_OUT
someVar: DINT;
END_VAR
VAR
_wrapped_obj: POINTER TO FinalBlock;
END_VAR
_wrapped_obj^(someVar := someVar);
//////
METHOD FB_Init: BOOL
VAR_INPUT
bInitRetains: BOOL;
bInCopyCode: BOOL;
END_VAR
VAR_IN_OUT
wrappedObj: FinalBlock;
END_VAR
THIS^._wrapped_obj := ADR(wrappedObj);
//////
METHOD GetSomeVarMethod : DINT
GetSomeVarMethod := THIS^.someVar;
//////
METHOD GetWrappedObjP : POINTER TO FinalBlock
GetWrappedObjP := THIS^._wrapped_obj;
PROGRAM SR_Main
VAR
original: FinalBlock;
someVar: DINT := 5;
wrap: Wrapper(original);
getVar: DINT;
END_VAR
wrap(someVar := someVar); // use this instead of "original(someVar := someVar);"
getVar := wrap.GetSomeVarMethod(); // getVar = 5
编辑:如果您要使用引用(或指针),需要注意的一件事是无效引用异常。你会在这两种情况下得到它们:
- 如果在设置变量之前访问它:
getVar := wrap.GetSomeVarMethod(); // calling this'll try to access someVar
wrap(someVar := someVar);
- 您忘记了应该使用包装器而不是被包装的对象:
original(someVar := someVar); // should have called "wrap(someVar := someVar);" instead!
getVar := wrap.GetSomeVarMethod();
为避免这种情况,您可以尝试:
- 在访问它之前检查参考:
METHOD GetSomeVarMethod : DINT
IF __ISVALIDREF(THIS^.someVar) THEN
GetSomeVarMethod := THIS^.someVar;
ELSE
GetSomeVarMethod := -1;
END_IF
或者
TYPE OPTIONAL
STRUCT
value: DINT;
error: BOOL;
END_STRUCT
END_TYPE
METHOD GetSomeVarMethod : OPTIONAL
IF __ISVALIDREF(THIS^.someVar) THEN
GetSomeVarMethod.value := THIS^.someVar;
ELSE
GetSomeVarMethod.error := TRUE;
END_IF
但是,如果用户忘记调用wrap(someVar := someVar);
并且只调用过,original(someVar := someVar);
那么 someVar 将永远无效。
- 不要将对象传递给包装器,而是让包装器完全创建和管理对象:
FUNCTION_BLOCK Wrapper
VAR_IN_OUT
someVar: DINT;
END_VAR
VAR
// with the 'no_init' attribute, we can let our FB_Init method initialize this object using user given arguments.
// If FinalBlock doesn't have any custom initialization arguments, you can skip this attribute and the FB_init code below.
{attribute 'no_init'}
_wrapped_obj: FinalBlock;
END_VAR
_wrapped_obj(someVar := someVar);
//////
METHOD FB_Init: BOOL
VAR_INPUT
bInitRetains: BOOL;
bInCopyCode: BOOL;
// FinalBlock initialization arguments
END_VAR
THIS^._wrapped_obj.FB_Init( (* initialization arguments *) );
无论哪种方式,我都建议您提供有关如何正确使用包装器并避免错误的良好文档。
或者,如果您想要将功能块传递给一个函数并访问该函数内的 VAR_IN_OUT 变量的值,您可以将该值与功能块一起传递(因为如果它是 VAR_IN_OUT,您应该可以访问反正原创):
VAR
original: FinalBlock;
someVar: DINT := 5;
END_VAR
original(someVar := someVar);
getVar := SomeFunction(obj := original, someVar := someVar);
或者:
TYPE Bundle :
STRUCT
obj: REFERENCE TO FinalBlock;
someVar: REFERENCE TO DINT;
END_STRUCT
END_TYPE
//////
VAR
original: FinalBlock;
someVar: DINT := 5;
bun: Bundle(obj := original, someVar := someVar);
END_VAR
original(someVar := someVar);
getVar := SomeFunction(bundle := bun);