c # — выделение массива строк из управляемого в нативный код

У меня есть управляемая функция со следующим объявлением (как интерфейс, так и реализация):

[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
String[] ManagedFunction()
{
String[] foo = new String[1];
foo[0] = "bar";
return foo;
}

Существует также собственный интерфейс C ++ с теми же методами, что и управляемый интерфейс, внутри этого интерфейса этот метод имеет следующее объявление:

void ManagedFunction(SAFEARRAY* foo);

Эта функция вызывается собственным кодом следующим образом:

void NativeFunction(ManagedBinding binding)
{
CComSafeArray<BSTR> cComSafeArray;
cComSafeArray.Create();
LPSAFEARRAY safeArray = cComSafeArray.Detach();
binding.comObject->ManagedFunction(safeArray);
}

Я не уверен, что я делаю неправильно, но после того, как моя управляемая функция была вызвана, safeArray кажется, что значения мусора, что-то идет не так, когда маршалинг возвращаемого значения возвращается к нативному коду. Может ли кто-то с большим опытом, чем я, с .Net Interop, пожалуйста, пролить свет на это? Кроме того, может быть уместно упомянуть, что у меня не было проблем с возвратом ValueTypes из моей управляемой функции (boolean если вам интересно), что-то о возвращении String Массив все портит. Спасибо!

6

Решение

1) Ваша функция возвращает SAFEARRAYтак почему вы выделяете его перед вызовом функции?
2) ManagedFunction должен вернуть SAFEARRAYтак что он должен получить SAFEARRAY* чтобы иметь возможность вернуть его! так что вы должны сказать:

LPSAFEARRAY lpsa;
binding.comObject->ManagedFunction(&lpsa);
CComSafeArray<BSTR> cComSafeArray;
cComSafeArray.Attach(lpsa);
0

Другие решения

Ну, я наконец-то получил его на работу. Я создал управляемое представление SAFEARRAY называется ManagedSafeArray (украдено отсюда: http://social.msdn.microsoft.com/Forums/en-US/clr/thread/6641abfc-3a9c-4976-a523-43890b2b79a2/):

[StructLayout(LayoutKind.Sequential)]
struct ManagedSafeArray
{
public ushort   dimensions;     // Count of dimensions in the SAFEARRAY
public ushort   features;       // Flags to describe SAFEARRAY usage
public uint     elementSize;    // Size of an array element
public uint     locks;          // Number of times locked without unlocking
public IntPtr   dataPtr;        // Pointer to the array data
public uint     elementCount;   // Element count for first (only) dimension
public int      lowerBound;     // Lower bound for first (only) dimension
}

Я изменил подпись моего метода на:

void ManagedMethod(ref ManagedSafeArray foo);

Внутри моего метода я вручную обновил dataPtr поле по телефону Marshal.AllocCoTaskMem(...) а затем скопировал строки, которые я хотел SAFEARRAY содержать.

Я понятия не имею, почему CLR не смог автоматически упорядочить параметры в нативный код и из него, и я все равно буду признателен, если кто-нибудь попытается объяснить это.

0

По вопросам рекламы [email protected]