Пишу ОРС (COM out of proc) сервер на С#. Возникла проблеммы с реализацией интерфейса IEnumString. Класс реализующий IEnumString выглядит следующим
образом:
class EnumString : IEnumString
{
public List<string> lStr;
private int currentpos;
public EnumString()
{
lStr=new List<string>();
currentpos = 0;
}
public int Next(int celt, [OutAttribute] string[] rgelt, IntPtr pceltFetched)
{
int i = 0;
List<string> ResultList = new List<string>();
while ((i < celt) && (currentpos < lStr.Count))
{
ResultList.Add(lStr[currentpos]);
i++;
currentpos++;
}
GC.KeepAlive(ResultList);
rgelt = ResultList.ToArray();
Marshal.StructureToPtr(i, pceltFetched, false);
return (i == celt) ? HRESULTS.S_OK : HRESULTS.S_FALSE;
}
public int Skip(int celt)
{
if (currentpos + celt <= lStr.Count)
{
currentpos += celt;
return HRESULTS.S_OK;
}
else
{
currentpos = lStr.Count;
return HRESULTS.S_FALSE;
}
}
public void Reset()
{
currentpos = 0;
}
public void Clone(out IEnumString ppenum)
{
throw new System.NotImplementedException();
}
public void Add(string newMember)
{
lStr.Add(newMember);
}
public bool Remove(string s)
{
return lStr.Remove(s);
}
}
На стороне клиента я работаю с ним следующим образом
g_pIOPCBrowse->QueryOrganization(&o);
if(o == OPC_NS_HIERARCHIAL)
{
hr = g_pIOPCBrowse->BrowseOPCItemIDs(OPC_FLAT, L""/*NULL*/, VT_EMPTY, 0, &pEnumString);
}
else
{
hr = g_pIOPCBrowse->BrowseOPCItemIDs(OPC_FLAT, L""/*NULL*/, VT_EMPTY, 0, &pEnumString);
}
if(FAILED(hr))
{
Log->AddString(_T("Error: BrowseOPCItemIDs()"));
}
if(hr == S_OK)
{
LPOLESTR pszName = NULL;
LPOLESTR pszTMP = NULL;
ULONG count = 0;
Log->AddString(_T(""));
Log->AddString(_T("There are following items on the server:"));
while((hr = pEnumString->Next(1, &pszName, &count)) == S_OK)
{
g_pIOPCBrowse->GetItemID(pszName,&pszTMP);
swprintf(lnItem.data.wszName,100,_T("%s"),pszTMP);
if(!strcmp(sz3,".")) strcpy(sz3,"VT_EMPTY");
if(!stricmp(sz3,"VT_I2")) lnItem.data.vt=VT_I2;//TestItem[nTestItem].vt = VT_I2;
else if(!stricmp(sz3,"VT_I4")) lnItem.data.vt=VT_I4;//TestItem[nTestItem].vt = VT_I4;
else if(!stricmp(sz3,"VT_EMPTY")) lnItem.data.vt=VT_EMPTY;//TestItem[nTestItem].vt = VT_EMPTY;
else if(!stricmp(sz3,"VT_R4")) lnItem.data.vt=VT_R4;//TestItem[nTestItem].vt = VT_R4;
else if(!stricmp(sz3,"VT_R8")) lnItem.data.vt=VT_R8;//TestItem[nTestItem].vt = VT_R8;
else if(!stricmp(sz3,"VT_BOOL")) lnItem.data.vt=VT_BOOL;//TestItem[nTestItem].vt = VT_BOOL;
else
{
Log->AddString(_T("Error: valid types: VT_EMPTY, VT_I2, VT_I4, VT_R4, VT_R8, VT_BOOL"));
continue;
}
ItemDef.szAccessPath = L"";;
ItemDef.szItemID = lnItem.data.wszName;//TestItem[nTestItem].wszName;
ItemDef.bActive = TRUE;
ItemDef.hClient = g_dwClientHandle++;
ItemDef.dwBlobSize = 0;
ItemDef.pBlob = NULL;
ItemDef.vtRequestedDataType = lnItem.data.vt;//TestItem[nTestItem].vt;
lnItem.data.hClient=ItemDef.hClient;
hr = g_pIOPCItemMgt->AddItems(1, &ItemDef, &pItemResult, &pErrors);
if(FAILED(hr))
{
Log->AddString(_T("Error: AddItem()"));
continue;
}
hr = S_OK;
if(FAILED(pErrors[0]))
{
Log->AddString(_T("Error: AddItem() item"));
continue;
}
lnItem.data.hServer = pItemResult->hServer;
lnItem.data.vt = pItemResult->vtCanonicalDataType;
nTestItem++;
::CoTaskMemFree(pItemResult);
::CoTaskMemFree(pErrors);
lData.insertAtBack(lnItem);
count_elements_spisok++;
::CoTaskMemFree(pszName);
i++;
}
pEnumString->Release();
}
В итоге,в методе Next в pszName содержиться указатеь 0x00000000. Уже голову себе сломал в чем тут дело,в дебагере видно что Next на сервере вызываеться,все проходит нормально,в count потом содержиться 1,то есть все нормально передаеться,а вот со строкой проблеммы. Помогите решить эту проблемму.