私の同僚は、次の方法でアンマネージ ライブラリから System::String オブジェクトに 2 バイト文字を入力しています。
RFC_PARAMETER aux;
Object* target;
RFC_UNICODE_TYPE_ELEMENT* elm;
elm = &(m_coreObject->m_pStructMeta->m_typeElements[index]);
aux.name = NULL;
aux.nlen = 0;
aux.type = elm->type;
aux.leng = elm->c2_length;
aux.addr = m_coreObject->m_rfcWa + elm->c2_offset;
GlobalFunctions::CreateObjectForRFCField(target,aux,elm->decimals);
GlobalFunctions::ReadRFCField(target,aux,elm->decimals);
GlobalFunctions::CreateObjectForRFCField は System::String オブジェクトを作成し、スペース (パディング用) で満たされて、アンマネージ ライブラリが最大長を次のように指定します。
static void CreateObjectForRFCField(Object*& object, RFC_PARAMETER& par, unsigned dec)
{
switch (par.type)
{
case TYPC:
object = new String(' ',par.leng / sizeof(_TCHAR));
break;
// unimportant afterwards.
}
}
また、GlobalFunctions::ReadRFCField() は、データをライブラリから作成された String オブジェクトにコピーし、スペース パディングを保持します。
static void ReadRFCField(String* target, RFC_PARAMETER& par)
{
int lngt;
_TCHAR* srce;
switch (par.type)
{
case TYPC:
case TYPDATE:
case TYPTIME:
case TYPNUM:
lngt = par.leng / sizeof(_TCHAR);
srce = (_TCHAR*)par.addr;
break;
case RFCTYPE_STRING:
lngt = (*(_TCHAR**)par.addr != NULL) ? (int)_tcslen(*(_TCHAR**)par.addr) : 0;
srce = *(_TCHAR**)par.addr;
break;
default:
throw new DotNet_Incomp_RFCType2;
}
if (lngt > target->Length) lngt = target->Length;
GCHandle gh = GCHandle::Alloc(target,GCHandleType::Pinned);
wchar_t* buff = reinterpret_cast<wchar_t*>(gh.AddrOfPinnedObject().ToPointer());
_wcsnset(buff,' ',target->Length);
_snwprintf(buff,lngt,_T2WFSP,srce);
gh.Free();
}
現在、時折、_snwprintf 呼び出しでアクセス違反が発生することがあります。私の質問は本当に: 長さにパディングされた文字列を作成し (理想的には内部バッファーを事前に割り当てるために)、GCHandle::Alloc と上記の混乱を使用して文字列を変更することは適切ですか?
はい、私は System::String オブジェクトが不変であると想定されていることを知っています - 私は決定的な「これは間違っていて、ここに理由があります」を探しています。
ありがとう、エリ。