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