2012-01-05 2 views
5

Ho una libreria nativa con alcuni nativi ntype in esso e vorrei p/invocare alcune funzioni in esso.PInvoke - Come eseguire il marshalling per 'SomeType * []'?

ho potuto schierare per:

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

ma non sanno come fare per:

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

Almeno IntPtr[] non ha funzionato.

Modifica

La funzione non gestita che sto cercando di schierare con è:

extern mxArray* mclCreateSimpleFunctionHandle(mxFunctionPtr fcn); 

dove mxFunctionPtr è:

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

questo rappresenta una chiamata per la seguente funzione MATLAB firma:

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

Ovviamente, dalle mie aspettative, questo puntatore a funzione dovrebbe fornire me con 2 liste di mxArray*:

  • La lista degli argomenti di input (cioè prhs, inizializzato dalla parte di MATLAB)
  • La lista degli argomenti di output (cioè plhs, tutto inizializzato a zero, ma in cui avrei dovuto scrivere in)

Attualmente dai test che ho fatto, esso restituisce solo per primati mxArray* in plhs e prhs liste

+0

funzioni C che richiedono puntatori e gli array sono irrimediabilmente ambigui. Non c'è differenza tra ntype ** e ntype * [] a meno che tu non abbia dato in qualche modo una semantica differente nel tuo codice. –

risposta

1

capito

Il marshalling corretto per 'SomeTime* []' in:

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); 

Spiegazione

MarshalAs attributo segnala marshalling SomeTime*[] come LPArray di IntPtr, dove la dimensione della matrice è contenuta dal parametro di funzione in corrispondenza dell'indice a base zero SizeParamIndex

2

prima cosa da fare è quello di tradurre il vostro nativo ntype in un gestita struct.

Per esempio:

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

Poi si definisce il metodo con un semplice IntPtr parametro nel codice C#.

[DllImport] 
static void foo1(IntPtr myParam); 

Infine ecco come lo si utilizza:

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); 
    } 
} 
+0

Perché non semplicemente non definisce la struttura in entrambi i suoi codici C# e C++ e invia l'indirizzo del puntatore al codice C++, il codice suggerito può portare le persone in difficoltà. –

+0

Grazie a @ken2k e @Ramhound per il tuo aiuto. Penso che non ho davvero bisogno di avere la struttura, solo un puntatore ad esso va bene per me. In effetti sto cercando di risolvere chiamando 'mclCreateSimpleFunctionHandle' come descritto in [collegamento] (http://stackoverflow.com/q/7892254/684399). Apparentemente, questa funzione sta ritornando solo per un puntatore al primo 'mxArray *' e sto cercando di ottenere l'elenco completo di 'mxArray *' (non mi interessa 'mxArray' stesso) ... Almeno per lettori su questo altro post, suppongo di essere sul mio modo di risolverlo. – CitizenInsane