Вызов управляемого метода API с типом параметра VARIANT из C # - PullRequest
1 голос
/ 06 февраля 2012

У меня есть ActiveX DLL, которую я пытаюсь использовать в своем приложении C #.Большинство методов взаимодействия работают.У меня проблемы со следующим методом (неуправляемое определение):

HRESULT SendData([in] long lChID, [in] short nIndex, 
    [in] VARIANT vData, [out, retval] VARIANT_BOOL *bResult);

Тип данных VARIANT необычен для меня, и я не знаю, что с ним делать, как COM иmarshalling - новая тема для меня.

BOOL CControl::SendData(long lChID, short nIndex, const VARIANT& vData)
{
    BOOL result;
    static BYTE parms[] = VTS_I4 VTS_I2 VTS_VARIANT;

    InvokeHelper(0x1f, DISPATCH_METHOD, VT_BOOL,
        (void*)&result, parms, lChID, nIndex, &vData);

    return result;
}

Я использовал инструмент .NET AxImp.exe , чтобы получить управляемую оболочку для метода:

[DispId(31)]
[MethodImpl(MethodImplOptions.InternalCall,
    MethodCodeType = MethodCodeType.Runtime)]
public virtual bool SendData([In] int lChID, [In] short nIndex, 
    [MarshalAs(UnmanagedType.Struct), In] object vData);

Правильно ли сгенерирована оболочка метода C #?

Как правильно инициализировать и заполнить параметр vData?

РЕДАКТИРОВАТЬ:

ЕщеПример кода, помогающий расшифровать 3-й параметр VARIANT.

VARIANT var;
VariantInit(&var);

var.vt = VT_UI1 | VT_BYREF;
var.pbVal = (unsigned char *)pSend;

if (!m_Control.SendData(m_lCurChID, m_combo.GetCurSel() + 1, var))
    AfxMessageBox(_T("SendData failed"));

* var.vt и var.pbVal мне не известны.Есть ли соответствующий код в C #?

1 Ответ

1 голос
/ 07 февраля 2012

Проверьте метод System.Runtime.InteropServices.Marshal.GetNativeVariantForObject() . Предполагая, что вы знаете, каким должно быть фактическое содержимое vData, вы сможете определить сигнатуру взаимодействия с IntPtr и передать результат этого метода в.

Ваша подпись должна быть примерно такой:

public virtual bool SendData(
    [In] int lChID, 
    [In] short nIndex, 
    [MarshalAs(UnmanagedType.Struct), In] IntPtr vData);

в то время как код вызова будет:

MyClass vData = ...;// build the actual data. 
IntPtr variantPtr = Marshal.AllocHGlobal(Marshal.SizeOf(vData ) + ???); // Allocate the space. I'm not entirely sure how much space you need here in addition to the base object size.
Marshal.GetNativeVariantForObject(vData , variantPtr); //fills the allocated memory with the VARIANT.

Проходя сейчас, кажется, есть несколько вопросительных знаков. Вот почему лучший способ действий - позволить маршаллеру по умолчанию выполнять свою работу. Если ваши vData - это byte [], просто определите функцию взаимодействия с помощью byte [] и посмотрите, что произойдет.

...