Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
How to use Variant to pass array from C++ client to VFP
Message
From
31/03/2011 05:54:08
 
General information
Forum:
Visual FoxPro
Category:
COM/DCOM and OLE Automation
Environment versions
Visual FoxPro:
VFP 9 SP1
OS:
Windows 7
Network:
Windows 2003 Server
Database:
Visual FoxPro
Application:
Desktop
Miscellaneous
Thread ID:
01505541
Message ID:
01505654
Views:
54
>I have created an EXE COM server in VFP that contains a function that accepts an array from the client, and fills that array with data. The array should be an array of byte, but for now, I would be happy if I could get an array of any data type to work.
>
>I have gotten this to work with a VFP client, but not with a C++ client.
>
>When I use a function statement that defines the incoming array as char @, C++ generates a wrapper from the TypeLib of the COM server that says the calling sequence is a VARIANT*. But, this doesn't work.
>
>Today, I thought that since C++ was sending a Variant, I would try declaring the function as follows:
>
>   FUNCTION GetFBDBlob(nFileID AS Integer, aBlobData AS Variant ) AS Integer
>
>This works with the VFP client when I call with a reference to a char array, like so:
>
>   DIMENSION aBlobData[nFileSize] AS char
>   nResult = oFBD.GetFBDBlob(nFileID, @aBlobData)
>
>
>In C++ I use the following code to set up a Variant and pass it to GetFBDBlob
>
>	SAFEARRAY* pSA = SafeArrayCreateVectorEx(VT_UI1, 0, nFileSize, NULL);
>	VARIANT vaBlobData;
>	VariantInit(&vaBlobData);
>	vaBlobData.vt = VT_ARRAY | VT_BYREF | VT_UI1;
>	vaBlobData.pparray = &pSA;
>	lResult = pFBDDBA->GetFBDBlob(nFileID, vaBlobData);
>
>
>I have also tried a variation of this:
>
>	SAFEARRAY* pSA = SafeArrayCreateVectorEx(VT_UI1, 0, nFileSize, NULL);
>	VARIANT vaBlobData;
>	VariantInit(&vaBlobData);
>	vaBlobData.vt = VT_ARRAY | VT_UI1;
>	vaBlobData.parray = pSA;
>	lResult = pFBDDBA->GetFBDBlob(nFileID, vaBlobData);
>
>
>GetFBDBlob() contains a call to ALEN right at the beginning: ALEN(aBlobData)
>
>While this works in VFP, either of my two formulations in the C++ client gets an error saying "ABLOBDATA is not an array"
>
>I have also modified this so that the VFP COM server is expecting a reference to a Variant. That also works with the VFP client, but not with the C++ client passing a pointer to the Variant.
>
>Surely there must be some syntax that allows me to pass an array by reference into a VFP COM server. Does anyone know what it is?
>
>Or, does anyone know of a strategy that will let me see where this is failing in VFP?
>
>Thanks,
>Jim
Here's some code I found for Variants - look at the v1 and v2 variables:
//These 2 macros make it easier to call methods on VFP servers.
#define XDOCMD(cmd) v1 = cmd;v2 = pmyclass->mydocmd(&v1);
#define XDOMETH(meth, cmd) v1 = cmd; v2 = pmyclass->##meth(&v1)
int CThreadObj::VirtualThreadStart() {
	char szBuf[1000];
	int i;
	CoInitialize(0);
	using namespace myserver;
	ImyclassPtr pmyclass;	// declare a smart ptr to the server
	pmyclass.CreateInstance("myserver.myclass");
	_variant_t v1,v2;
	long vfpthreadid;
	XDOCMD("declare integer GetCurrentThreadId in win32api");

	for (i = 0 ; i < NUMITER ; i++) {
		//ask the server for the thread ID
		XDOMETH(myeval,"GetCurrentThreadId()");	
		vfpthreadid = v2.lVal;
		wsprintf(szBuf,
			"i = %d Thread # %d ID = %d VFPID = %d\n",
			i,m_nthread,m_threadId, vfpthreadid);
		//show the output in the VC Output Window
		OutputDebugString(szBuf);
	}
	pmyclass = 0;				// release the server
	CoUninitialize();

	return 0;
}

//this is the static real thread starting proc
unsigned long __stdcall CThreadObj::RealThreadStart(void *p) {
	CThreadObj *pobj;
	//get a pointer to the thread object
	pobj = (CThreadObj *) p;
	// and call it's thread start routine
	pobj->VirtualThreadStart();
	return 0;
}

int WINAPI WinMain(HINSTANCE , HINSTANCE , LPSTR , int ) {
	CThreadObj threads[NUMTHREADS];	//decl array of CThreadObj objects
	HANDLE harray[NUMTHREADS];		//array of handles
	for (int i = 0 ; i < NUMTHREADS ; i++) {
		threads[i].m_nthread = i;	//record the thread #
		harray[i] =		//record the thread ID
			CreateThread(NULL,0, 
				CThreadObj::RealThreadStart, //thd strt addr
				(void *)&threads[i], //parm to pass to thrd
				NULL, 
				&threads[i].m_threadId);
	}
	//now wait for all the threads to finish
	WaitForMultipleObjects(NUMTHREADS, harray, TRUE, INFINITE);
	return 0;

}
Previous
Reply
Map
View

Click here to load this message in the networking platform