Listing 1

// Define the function pointer for PB_GetVM
typedef PBXEXPORT PBXRESULT (*P_PB_GetVM)(IPB_VM** vm);

// constructor
CPBInvoker::CPBInvoker(LPCTSTR LibList[], int libNum, LPCTSTR appName)
{ 
_hinst = NULL; // a member variable to hold the DLL handle
IPB_VM* pbvm;

	_hinst = LoadLibrary("pbvm100.dll"); // step2: load PBVM
	if ( _hinst == NULL ) {
		throw "Loaded PBVM successfully";
	}
	// step 3: Get PBVM reference
	P_PB_GetVM getvm = (P_PB_GetVM)GetProcAddress(_hinst,"PB_GetVM");
	if (getvm == NULL) {
		throw "PB_GetVM failed";
	}

getvm(&pbvm);
	if (pbvm == NULL) {
		throw "getvm failed";
	}

	// step 4: Create IPB_Session instance, LibList is an array holds the pbl file names
	if ( pbvm->CreateSession(appName, LibList, libNum, &_session) != PBX_OK ) {
       throw "Error in CreateSession";
}
}

// destructor
CPBInvoker::~CPBInvoker()
{
	// step 13: Release IPB_Session
	if( NULL != _session ) {
		_session->Release();
	}
	// unload PBVM DLL
	if( NULL != _hinst ) {
		FreeLibrary(_hinst);
	}
}

// Call the NVO method
void CPBInvoker::barcode(LPCTSTR text, LPCTSTR format, char* code)
{
    // step 5: Find the group, n_automation is the NVO's name
    pbgroup group = _session->FindGroup("n_automation",  pbgroup_userobject);

    if (group == NULL) throw "n_automation is not found!";

    // step 6: Find the class, n_automation is the NVO's name
    pbclass cls = _session->FindClass(group,"n_automation");

    if (cls == NULL) throw "n_automation class not found!";

    // step 7: Create an instance of the PowerBuilder object
    pbobject pbobj = _session->NewObject(cls);

    // PBCallInfo contains arguments and return value
    PBCallInfo ci;

   // step 8: GetMethodID to get the method. "SSS" is the signature string, fn_barcode is
   // the function name
    pbmethodID mid = _session->GetMethodID(cls, "fn_barcode",  PBRT_FUNCTION, "SSS");

    // step 9: Initialize call info structure based on method ID
    _session->InitCallInfo(cls, mid, &ci);
 
   // step 10: Fill in parameters.
    ci.pArgs-> GetAt(0)->SetString(text);
    ci.pArgs-> GetAt(1)->SetString(format);
 
   // step 11: invoke the method
    _session->InvokeObjectFunction(pbobj, mid, &ci);

    // step 12: Retrieve the return value, code is a valid memory
    // buffer passed in by the caller
    pbstring ret = ci.returnValue->GetString();
    strcpy( code, _session->GetString(ret) );

   // step 13: Release the PBCallInfo structure
   _session->FreeCallInfo( &ci );
}


Listing 2

#define PBINVOKER_API __declspec(dllexport)

PBINVOKER_API void barcode(LPCTSTR specimen_formatted, LPCTSTR spcimen_id, char *code)
{
	// _invoker is a global variable holds the reference of the PBInvoker object
	if( NULL != _invoker ) {
		// call the NVO method
		_invoker->barcode(specimen_formatted, spcimen_id, code);
	} 
}

PBINVOKER_API void initPBSession(LPCTSTR libList[], int libNum, LPCTSTR appName)
{
	// init the IPB_Session 
	if( NULL == _invoker ) {
		// instantiate the CPBInvoker wrapper class
 		_invoker = new CPBInvoker(libList, libNum, appName);
	}
}

PBINVOKER_API void closePBSession()
{
	// clean up
	if( NULL != _invoker ) {
		// delete the wrapper object
		delete _invoker;
		_invoker = NULL;
	}
}