在COM中使用数组

Scroll Down

一、字符串数组

关键代码:
组件方:

STDMETHODIMP CTestArray::Show1(SAFEARRAY *pSa)
{
	// TODO: Add your implementation code here
	if (pSa != NULL)
	{
		VARTYPE vt;
		SafeArrayGetVartype(pSa, &vt);//判别数组元素类型
		if (vt != VT_BSTR)
			return S_FALSE;

		long lLBound, lUBound;
		BSTR *pBstr;
		char strText[1024] = "", strTemp[100];

		SafeArrayGetLBound(pSa, 1, &lLBound);//一维数组下标
		SafeArrayGetUBound(pSa, 1, &lUBound);//一维数组上标
		SafeArrayAccessData(pSa, (void**)&pBstr);

		for (long i = lLBound; i <= lubound; i++) {
			wcstombs(strTemp, *(pBstr + i), 100);
			strcat(strText, strTemp);
		}
		SafeArrayUnaccessData(pSa);
		::MessageBox(NULL, strText, "Use Array in COM DLL", MB_OK); return S_OK;
	}
	return S_FALSE;
}

客户方:

void CTestDlg::OnButton1() {
	USES_CONVERSION;//想用T2OLE就必须加上这一句

	CoInitialize(NULL);

	ITestArrayPtr ptr;
	ptr.CreateInstance(__uuidof(TestArray));

	SAFEARRAYBOUND pSab[1];
	pSab[0].lLbound = 0;
	pSab[0].cElements = 3;

	SAFEARRAY *pSa;
	pSa = SafeArrayCreate(VT_BSTR, 1, pSab);

	BSTR *pBstr;
	SafeArrayAccessData(pSa, (void**)&pBstr);
	*(pBstr) = SysAllocString(T2OLE("BSTR1 "));//也可用A2W
	*(pBstr + 1) = SysAllocString(T2OLE("BSTR2 "));
	*(pBstr + 2) = SysAllocString(T2OLE("BSTR3 "));
	SafeArrayUnaccessData(pSa);

	ptr->Show1(pSa);

	SafeArrayDestroy(pSa);

	ptr.Release();

	CoUninitialize();
}

二、自定义数据结构数组

关键代码:
组件方:

STDMETHODIMP CTestArray::Show2(SAFEARRAY *pSa)
{
	if (pSa != NULL)
	{
		VARTYPE vt;
		SafeArrayGetVartype(pSa, &vt);//判别数组元素类型
		if (vt != VT_RECORD) //VT_RECORD型
			return S_FALSE;

		long lLBound, lUBound;
		STUDENT *pStudent;
		char strText[4096] = "", strTemp[100];

		SafeArrayGetLBound(pSa, 1, &lLBound);//一维数组下标
		SafeArrayGetUBound(pSa, 1, &lUBound);//一维数组上标
		SafeArrayAccessData(pSa, (void**)&pStudent);

		for (long i = lLBound; i <= lubound; i++)
		{
			wcstombs(strTemp, (*(pStudent + i)).name, 100);
			strcat(strText, "name=");
			strcat(strText, strTemp);
			strcat(strText, " /n");
			sprintf(strTemp, "grade="%d / n"," (*(pStudent + i)).grade);
			strcat(strText, strTemp);
			if ((*(pStudent + i)).sex = "=" 0)
				strcpy(strTemp, "male/n");
			else strcpy(strTemp, "female/n");
			strcat(strText, "sex=");
			strcat(strText, strTemp);
			if ((*(pStudent + i)).graduate)
				strcpy(strTemp, " true/n");
			else
				strcpy(strTemp, "false/n");
			strcat(strText, "graduate:");
			strcat(strText, strTemp);
			strcat(strText, "/n");
		}
		SafeArrayUnaccessData(pSa);
		::MessageBox(NULL, strText, "Use Array in COM DLL", MB_OK);
		return S_OK;
	}
	return S_FALSE;
}

客户方:

void CTestDlg::OnButton2()
{
	const GUID GUID_STUDENT
		= "{0xF7D09422,0xB295,0x11d4,{0x98,0xDB,0x00,0x80,0xC8,0xF5,0xB2,0xE4}}";
	CoInitialize(NULL);
	ITypeInfo *pTypeInfo = NULL;
	ITypeLib *pTypelib = NULL;
	IRecordInfo *pRecInfo = NULL;
	SAFEARRAY *psaStudent = NULL;
	SAFEARRAYBOUND rgbounds = { 4, 0 };
	STUDENT *pStudentStruct = NULL;
	ITestArrayPtr ptr;
	LoadRegTypeLib(LIBID_USEARRAYLib, 1, 0, GetUserDefaultLCID(), &pTypelib);
	pTypelib->GetTypeInfoOfGuid(GUID_STUDENT, &pTypeInfo);
	GetRecordInfoFromTypeInfo(pTypeInfo, &pRecInfo);
	pTypeInfo->Release();
	pTypelib->Release();

	//只有用VT_RECORD才能识别数据结构
	psaStudent = SafeArrayCreateEx(VT_RECORD, 1, &rgbounds, pRecInfo);
	pRecInfo->Release();

	SafeArrayAccessData(psaStudent, (void**)(&pStudentStruct));
	pStudentStruct[0].grade = 3;
	pStudentStruct[0].name = SysAllocString(L"Lostall");//用L更简单
	pStudentStruct[0].sex = male;
	pStudentStruct[0].graduate = true;
	pStudentStruct[1].grade = 8;
	pStudentStruct[1].name = SysAllocString(L"Nicesnower");
	pStudentStruct[1].sex = female;
	pStudentStruct[1].graduate = false;
	pStudentStruct[2].grade = 12;
	pStudentStruct[2].name = SysAllocString(L"Mike");
	pStudentStruct[2].sex = male;
	pStudentStruct[2].graduate = true;
	pStudentStruct[3].grade = 3;
	pStudentStruct[3].name = SysAllocString(L"Linda");
	pStudentStruct[3].sex = female;
	pStudentStruct[3].graduate = false;
	SafeArrayUnaccessData(psaStudent);

	ptr.CreateInstance(CLSID_TestArray);
	ptr->Show2(psaStudent);
	ptr.Release();

	CoUninitialize();
}