Step 4: Implement native classes and global functions
The implementation of each class must include the implementation
of the Invoke and Destroy methods,
as well as all the methods declared for the class. Invoke and Destroy are
methods of the IPBX_UserObject interface.
When the PowerBuilder application calls a method on the native
class, the PBVM calls the Invoke method, which
dispatches the call based on the method ID or method name. The method
name is used when the method is called dynamically.
The Invoke method must be coded to invoke
each method in the class. The example that follows shows a switch–case
statement that invokes either funcA or funcB,
depending on the value of the method ID. When the PowerBuilder application
has finished using an instance of a native class, the PBVM calls
the Destroy method.
This example does not show the implementation of the methods
of the class itself:
PBXRESULT MyClass::Invoke(IPB_Session *session, pbobject obj, pbmethodID mid, PBCallInfo *ci)
{
PBXRESULT result = PBX_OK;
switch (mid)
{
case mFunca:
result = funcA(session, obj, ci);
break;
case mFuncb:
result = funcB(session, obj, ci);
break;
default:
result = PBX_E_INVOKE_FAILURE;
break;
}
return result;
}
// Implementation of funcA and funcB not shown
void Destroy()
{
delete this;
}
The following PBX_InvokeGlobalFunction contains
the implementation of the three global functions included in the
description shown in "Step 3: Declare native classes
and global functions":
PBXEXPORT PBXRESULT PBXCALL PBX_InvokeGlobalFunction
(
IPB_Session* pbsession,
LPCTSTR functionName,
PBCallInfo* ci
)
{
PBXRESULT pbrResult = PBX_OK;
int arg1 = ci->pArgs->GetAt(0)->GetInt();
int arg2 = ci->pArgs->GetAt(1)->GetInt();
if (stricmp(functionName, "bitand") == 0)
{
ci->returnValue->SetInt(arg1 & arg2);
}else if (strcmp(functionName, "bitor") == 0)
{
ci->returnValue->SetInt(arg1 | arg2);
}else if (strcmp(functionName, "bitxor") == 0)
{
ci->returnValue->SetInt(arg1 ^ arg2);
}else
{
return PBX_FAIL;
}
return pbrResult;
}