PInvoke - Как выполнить поиск для SomeType * []? - PullRequest
5 голосов
/ 05 января 2012

У меня есть нативная библиотека с некоторыми нативными ntype, и я хотел бы запустить / вызвать некоторые функции.

Мне удалось собрать:

foo1(ntype** p) ==> foo1(IntPtr[] p)

Но не знаю, как это сделать:

foo1(ntype*[] p) ==> foo1(<???> p)

Как минимум IntPtr[] не сработало.

Редактировать

Неуправляемая функция, с которой я пытаюсь собраться:

extern mxArray* mclCreateSimpleFunctionHandle(mxFunctionPtr fcn);

, где mxFunctionPtr:

typedef void(*mxFunctionPtr)(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[]);

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

function [varargout] = callback(varargins)
%[
    %% Do callback code %%
%]

Очевидно, из моих ожиданий, этот указатель на функцию должен предоставить мне 2 списка mxArray*:

  • Список входных аргументов (т.е. prhs, инициализированных на стороне matlab)
  • Список выходных аргументов (т. Е. Plhs, все инициализированы в ноль, но в которые я должен записать)

В настоящее время из проведенных мною тестов он возвращается только для первых mxArray* в plhs и prhs списках

Ответы [ 2 ]

2 голосов
/ 06 января 2012

Понял

Правильная сортировка для 'SomeTime* []' в:

extern mxArray* mclCreateSimpleFunctionHandle(mxFunctionPtr fcn);
typedef void(*mxFunctionPtr)(int nlhs, mxArray* plhs[], int nrhs, mxArray* prhs[]);

есть:

// For function pointer
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public delegate void MCRInteropDelegate(int nlhs,
                                        [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 0)][Out] IntPtr[] plhs, 
                                        int nrhs,
                                        [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 2)][In] IntPtr[] prhs);

// For API function
[DllImport(DLLNAME, EntryPoint = "mclCreateSimpleFunctionHandle", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
private static extern IntPtr _mclCreateSimpleFunctionHandle(MCRInteropDelegate fctn);

Объяснение

Атрибут

MarshalAs указывает маршалу SomeTime*[] как LPArray из IntPtr, где размер массива содержится в параметре функции с нулевым индексом SizeParamIndex

2 голосов
/ 05 января 2012

Первое, что нужно сделать, это перевести ваш родной ntype в управляемый struct.

Например:

public struct Ntype
{
    public int Field1;
    public long Field2;
}

Затем вы определяете свой метод с помощью простого параметра IntPtr в своем коде C #.

[DllImport]
static void foo1(IntPtr myParam);

Наконец, вот как вы его используете:

IntPtr buffer = IntPtr.Zero;

try
{
    // Allocates a buffer. The size must be known
    buffer = Marshal.AllocHGlobal(0x1000);

    // Call to your unmanaged method that fills the buffer
    foo1(buffer);

    // Casting the unmanaged memory to managed structure that represents
    // your data
    Ntype obj = (Ntype)Marshal.PtrToStructure(buffer, typeof(Ntype));
}
finally
{
    // Free unmanaged memory
    if (buffer != IntPtr.Zero)
    {
        Marshal.FreeHGlobal(buffer);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...